hdu 4217 树状数组+二分搜索

Problem: http://acm.hdu.edu.cn/showproblem.php?pid=4217

给定1~n的n个数

依次求第ki小的数 删除该数 再求剩下的数中第ki+1小的数 删除...

求所有删除的数的和

用树状数组bit[]:bit[k](这里的bit[k]不是bit[k]本身的值,详见代码中find(k))表示小于等于 k 的数的个数

用二分搜索 搜索第ki大的数

#include<cstdio>
const int MAXN=270000;
int bit[MAXN];
int find(int k){//查找小于等于k的数的个数 
    int ret=0;
    while(k>0){
        ret+=bit[k];
        k-=k&-k;
    }
    return ret;
}
int work(int k,int n){
    int L=1,R=n;
    while(L<R){//二分搜索第k大的值 
        int M=(L+R)>>1;
        if(k>find(M))L=M+1;
        else R=M;
    }
    while(R<=n){//删除第k大的值 在树状数组中的形式为比k大的数 的bit[]-1 
        bit[R]--;
        R+=R&-R;
    }
    return L;
}
int main()
{
    int t,n,k,ki;
    scanf("%d",&t);
    for(int Case=1;Case<=t;Case++){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)bit[i]=i&-i;//树状数组实现 
        long long ans=0;
        for(int i=0;i<k;i++){
            scanf("%d",&ki);
            ans+=work(ki,n);
        }
        printf("Case %d: %I64d\n",Case,ans);
    }
    return 0;
}
View Code

想想 此题线段树、平衡数应该都可做

posted @ 2014-02-10 21:02  Cshhr  阅读(258)  评论(0编辑  收藏  举报