zoj2112 Dynamic Rankings 单点修改区间第k小

来源:互联网 发布:阿里大数据应用案例 编辑:程序博客网 时间:2024/05/21 17:54

题目:给你N个数,M个操作,操作分两种,(Q,L,R,K)询问区间[L,R]第K小的数,(C,L,R)把第L个数改为R。N<=50000,M<=10000

思路:主席树满足前缀和,因此可以用树状数组来维护。直接在原树上进行修改操作的空间复杂度是nlognlogn,会MLE。给树状数组单独开一棵主席树的空间复杂度是mlognlogn。因此要单独开一主席树,两者的和就是结果。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<list>#include<numeric>using namespace std;#define PI acos(-1.0)#define LL long long#define ULL unsigned long long#define INF 0x3f3f3f3f#define mm(a,b) memset(a,b,sizeof(a))#define PP puts("*********************");template<class T> T f_abs(T a){ return a > 0 ? a : -a; }template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}// 0x3f3f3f3f3f3f3f3f// 0x3f3f3f3fconst int maxn=6e4+50;const int maxm=2500010;int arr[maxn];//原数组int num[maxn],siz;//num离散化之后的数组int root[maxn],lson[maxm],rson[maxm],cnt[maxm];//根节点,左儿子,右儿子,区间内的数出现次数的前缀和int tot;int S[maxn];//树状数组的根节点int luse[maxn],ruse[maxn],llen,rlen;//查询时使用的树状数组的根节点void init(){    tot=1;    root[0]=lson[0]=rson[0]=cnt[0]=0;//建一棵空树    sort(num+1,num+siz+1);//离散化    siz=unique(num+1,num+siz+1)-num-1;}int Hash(int x){    return lower_bound(num+1,num+siz+1,x)-num;}int update(int rt,int pos,int val){    int newrt=tot++,temp=newrt;    cnt[newrt]=cnt[rt]+val;    int l=1,r=siz;    while(l<r){        int mid=(l+r)/2;        if(pos<=mid){            r=mid;            lson[newrt]=tot++;rson[newrt]=rson[rt];            newrt=lson[newrt];rt=lson[rt];        }        else{            l=mid+1;            lson[newrt]=lson[rt];rson[newrt]=tot++;            newrt=rson[newrt];rt=rson[rt];        }        cnt[newrt]=cnt[rt]+val;    }    return temp;}int lowbit(int i){    return i&(-i);}int n;void add(int i,int pos,int val){    while(i<=n){        S[i]=update(S[i],pos,val);        i+=lowbit(i);    }}int query(int left_rt,int right_rt,int k){    int l=1,r=siz;    while(l<r){        int mid=(l+r)/2;        int lsum=0,rsum=0;        for(int i=1;i<=llen;i++) lsum+=cnt[lson[luse[i]]];        for(int i=1;i<=rlen;i++) rsum+=cnt[lson[ruse[i]]];        int temp=rsum-lsum+cnt[lson[right_rt]]-cnt[lson[left_rt]];        if(temp>=k){            r=mid;            for(int i=1;i<=llen;i++) luse[i]=lson[luse[i]];            for(int i=1;i<=rlen;i++) ruse[i]=lson[ruse[i]];            left_rt=lson[left_rt];            right_rt=lson[right_rt];        }        else{            l=mid+1;            k-=temp;            for(int i=1;i<=llen;i++) luse[i]=rson[luse[i]];            for(int i=1;i<=rlen;i++) ruse[i]=rson[ruse[i]];            left_rt=rson[left_rt];            right_rt=rson[right_rt];        }    }    return l;}struct Node{    int kind,L,R,K;}ask[10010];int main(){    int T,N,M;    char str[10];    scanf("%d",&T);    while(T--){        siz=0;        scanf("%d%d",&N,&M);        n=N;        for(int i=1;i<=N;i++){            scanf("%d",&arr[i]);            num[++siz]=arr[i];        }        for(int i=1;i<=M;i++){            scanf("%s",str);            if(str[0]=='Q'){//查询操作                ask[i].kind=0;                scanf("%d%d%d",&ask[i].L,&ask[i].R,&ask[i].K);            }            else{//修改操作                ask[i].kind=1;                scanf("%d%d",&ask[i].L,&ask[i].R);                num[++siz]=ask[i].R;            }        }        init();        for(int i=1;i<=n;i++)            root[i]=update(root[i-1],Hash(arr[i]),1);        for(int i=1;i<=n;i++) S[i]=root[0];        for(int i=1;i<=M;i++){            if(ask[i].kind==0){                llen=rlen=0;                for(int j=ask[i].L-1;j>0;j-=lowbit(j)) luse[++llen]=S[j];                for(int j=ask[i].R;j>0;j-=lowbit(j)) ruse[++rlen]=S[j];                int ans=query(root[ask[i].L-1],root[ask[i].R],ask[i].K);                printf("%d\n",num[ans]);            }            else{                add(ask[i].L,Hash(arr[ask[i].L]),-1);                arr[ask[i].L]=ask[i].R;                add(ask[i].L,Hash(arr[ask[i].L]),1);            }        }    }    return 0;}


阅读全文
0 0
原创粉丝点击