bzoj 3196 Tyvj 1730 二逼平衡树(主席树)

来源:互联网 发布:手机遥控ppt软件 编辑:程序博客网 时间:2024/06/04 21:04

吃什么


Sol

写法同动态第k大
查询前驱后继有一些细节注意


Code

// by spli#include<cstring>#include<cstdio>#include<algorithm>#include<iostream>#define LL long longusing namespace std;const int N=50010;int n,m,r[N<<1],sz;LL a[N],b[N<<1],top,len;struct Tree{    int ls,rs;    int siz;}t[N*200];struct ques{    LL op,x,y,z;}q[N];int lft[N],rgh[N],A,B;int lowbit(int x){return x&(-x);}void update(int &p,int L,int R,int k,int d){     //t[++sz]=t[p];     //p=sz;     if(!p) p=++sz;     t[p].siz+=d;     if(L==R) return;     int mid=(L+R)>>1;     if(k<=mid) update(t[p].ls,L,mid,k,d);     else update(t[p].rs,mid+1,R,k,d);}void add(int pos,int k,int d){    for(int i=pos;i<=n;i+=lowbit(i))        update(r[i],1,len,k,d);}void ready(int L,int R){    L--;    A=B=0;    for(int i=L;i;i-=lowbit(i)) lft[++A]=r[i];    for(int i=R;i;i-=lowbit(i)) rgh[++B]=r[i];}void getlft(){    for(int i=1;i<=A;++i) lft[i]=t[lft[i]].ls;    for(int i=1;i<=B;++i) rgh[i]=t[rgh[i]].ls;}void getrgh(){    for(int i=1;i<=A;++i) lft[i]=t[lft[i]].rs;    for(int i=1;i<=B;++i) rgh[i]=t[rgh[i]].rs;}int getsum(){    int ret=0;    for(int i=1;i<=A;++i) ret-=t[t[lft[i]].ls].siz;    for(int i=1;i<=B;++i) ret+=t[t[rgh[i]].ls].siz;    return ret;}int getrank(int L,int R,int v){    if(L==R) return 1;    int mid=(L+R)>>1;    if(mid>=v){        getlft();        return getrank(L,mid,v);    }    else{        int sum=getsum();        getrgh();        return sum+getrank(mid+1,R,v);    }}int get_th(int L,int R,int k){    if(L==R) return L;    int mid=(L+R)>>1;    int sum=getsum();    if(k<=sum) return getlft(),get_th(L,mid,k);    else return getrgh(),get_th(mid+1,R,k-sum);}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i) scanf("%lld",&a[i]),b[++top]=a[i];    for(int i=1;i<=m;++i){        scanf("%lld%lld%lld",&q[i].op,&q[i].x,&q[i].y);        if(q[i].op==3) b[++top]=q[i].y;        else{            scanf("%lld",&q[i].z);            if(q[i].op==4||q[i].op==5) b[++top]=q[i].z;        }    }    b[++top]=2147483647;    b[++top]=-2147483647;    sort(b+1,b+1+top);    len=unique(b+1,b+1+top)-b-1;    for(int i=1;i<=n;++i){        int rk=lower_bound(b+1,b+1+len,a[i])-b;        add(i,rk,1);    }    for(int i=1;i<=m;++i){        if(q[i].op==1){            ready(q[i].x,q[i].y);            q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;            printf("%d\n",getrank(1,len,q[i].z));        }        if(q[i].op==2){            ready(q[i].x,q[i].y);            printf("%d\n",b[get_th(1,len,q[i].z)]);        }        if(q[i].op==3){            int rk=lower_bound(b+1,b+1+len,a[q[i].x])-b;            add(q[i].x,rk,-1);            rk=lower_bound(b+1,b+1+len,q[i].y)-b;            add(q[i].x,rk,1);            a[q[i].x]=q[i].y;        }        //lower_bound查的是第一个大于等于x的数,一次求前驱可以 get_th(1,len,rk-1)        // 后继必须 get_th(1,len,rk+num)        if(q[i].op==4){            ready(q[i].x,q[i].y);            q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;            int rk=getrank(1,len,q[i].z);            ready(q[i].x,q[i].y);            printf("%d\n",b[get_th(1,len,rk-1)]);        }        if(q[i].op==5){            q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;            ready(q[i].x,q[i].y);            int rk=getrank(1,len,q[i].z);            int num=-rk;            ready(q[i].x,q[i].y);            num+=getrank(1,len,q[i].z+1);            ready(q[i].x,q[i].y);            printf("%d\n",b[get_th(1,len,rk+num)]);        }    }    return 0;}