1. 程式人生 > >zoj 3635(樹狀陣列求K大)

zoj 3635(樹狀陣列求K大)

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;
}