hdu4217 Data Structure?

来源:互联网 发布:小米4支持4g网络吗 编辑:程序博客网 时间:2024/05/19 20:42

题目链接:点击打开链接



树状数组,每个区间保存此区间中有多少未取过的数,每次输入k,查区间内刚好是k个数的点,然后update(k,-1)。

对区间更新对点查询,对区间(a,b)加v操作:update(a,v),update(b,-v),对x点查询:正常quary(x)。

本题每次都更新至区间结尾,所以不需要update(b,-v)。


当需要确定第一个达到某值的点时,可使用:

int quary(int n){
    int cur=0;
    int k=0;
    for(int i=18;i>=0;i--){
           if(k+(1<<i)<=N&&cur+c[k+(1<<i)]<n){
                k+=(1<<i);
                cur+=c[k];
           }
    }
    return k+1;
}


cur+c[k+(1<<i)]<n)此处必须为小于而不是小于等于,因为得到的是应是第一个达到某值的,而算法是从大到小判定的,结果位置应是最接近某值的数+1。


结果用long long。。

代码:


#include <iostream>#include <cstdio>#include <cstring>#define FOR(i, x, y) for(int i = x; i <= y; i++)#define MS(x, y) memset(x, y, sizeof(x))using namespace std;int c[277777];int N,T,K;int lowbit(int n){    return (n&(-n));}void update(int n,int v){    while(n<=N){        c[n]+=v;        n+=lowbit(n);    }}int quary(int n){    int cur=0;    int k=0;    for(int i=18;i>=0;i--){           if(k+(1<<i)<=N&&cur+c[k+(1<<i)]<n){                k+=(1<<i);                cur+=c[k];           }    }    return k+1;}int main(){    int T;    cin>>T;    int cas=0;    while(T--){            scanf("%d%d",&N,&K);            FOR(i,0,N){                c[i]=0;            }            FOR(i,1,N){                update(i,1);            }            int t;            long long res=0;            FOR(i,1,K){                scanf("%d",&t);                int k=quary(t);                res+=k;                update(k,-1);            }            cout <<"Case "<<++cas<<": "<<res<<endl;    }    return 0;}
0 0