zoj 3635(樹狀陣列求K大)
阿新 • • 發佈:2019-02-15
zoj題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3635
解題報告人:GHQ(SpringWater)
題目大意:每次從編號1-n刪除一個數字,重新編號1-(n-1),重複操作,問你每次刪除的那個編號的最初編號是?
解題思路,利用樹狀陣列,求出第K大的編號是ans,則當前編號為k的最初編號為ans!
求最低位
int Lowbit(int t)
{
return t & ( t ^ ( t - 1 ) );
}
求前n項和:
int Sum(int end) { int sum = 0; while(end > 0) { sum += in[end]; end -= Lowbit(end); } return sum; } |
對某個元素進行加法操作:
void plus(int pos , int num)
{
while(pos <= n)
{
in[pos] += num;
pos += Lowbit(pos);
}
}
#include<stdio.h> #include<string.h> #define MAXN 50005 int res[MAXN],c[MAXN]; int find_kth(int k,int N) { int ans = 0, cnt = 0, i; for (i = 20; i >= 0; i--) { ans += (1 << i); if (ans >= N|| cnt + c[ans] >= k) ans -= (1 << i); else cnt += c[ans]; } return ans + 1; } int lowbit(int x) { return x & -x; } void add(int x, int num,int N) { for ( ; x <= N; x += lowbit(x)) c[x] += num; } int main() { int N,K,i,num; while(~scanf("%d",&N)) { memset(c,0,sizeof(c)); for(i=1;i<=N;i++)add(i,1,N); for(i=1;i<=N;i++) { scanf("%d",&K); res[i]=find_kth(K,N); add(res[i],-1,N); } scanf("%d",&N); for(i=1;i<=N;i++) { scanf("%d",&num); if(i<N) printf("%d ",res[num]); else printf("%d",res[num]); } printf("\n"); } return 0; }