zoukankan      html  css  js  c++  java
  • 高级数据结构模板

    1.线段树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    const int maxn=2e6+10;
    typedef long long ll;
    ll a[maxn],segt[maxn<<2],lazy[maxn<<2];
    int n,q,qu,xx,yy,zz; 
    void build(int x,int l,int r){
        if(l==r){segt[x]=a[l];return ;}
        build(lc,l,mid);build(rc,mid+1,r);
        segt[x]=segt[lc]+segt[rc];
    }
    void putdown(int x,int l_len,int r_len){
        segt[lc]+=lazy[x]*l_len;lazy[lc]+=lazy[x];
        segt[rc]+=lazy[x]*r_len;lazy[rc]+=lazy[x];
        lazy[x]=0;
    }
    void updata(int x,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){segt[x]+=(r-l+1)*v;lazy[x]+=v;return;}
        if(lazy[x]) putdown(x,mid-l+1,r-mid);
        if(ql<=mid) updata(lc,l,mid,ql,qr,v);
        if(qr>mid) updata(rc,mid+1,r,ql,qr,v);
        segt[x]=segt[lc]+segt[rc];
    }
    ll query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return segt[x];
        if(lazy[x]) putdown(x,mid-l+1,r-mid);
        if(qr<=mid) return query(lc,l,mid,ql,qr);
        else if(ql>mid) return query(rc,mid+1,r,ql,qr);
        return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);  
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d",&qu,&xx,&yy);
            if(qu==1){
            scanf("%d",&zz);
                updata(1,1,n,xx,yy,zz);
            }
            else printf("%lld
    ",query(1,1,n,xx,yy));
        }
        return 0;
    }
    codevs 线段树练习3
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    const int maxn=1e6+10;
    typedef long long ll;
    ll a[maxn],segt[maxn<<2][7],lazy[maxn<<2],temp[7];
    int n,q,xx,yy,zz; 
    char qu[10];
    using namespace std;
    void build(int x,int l,int r){
        if(l==r) {segt[x][a[l]%7]=1; return ;}
        build(lc,l,mid);build(rc,mid+1,r);
        for(int i=0;i<=6;i++){segt[x][i]=segt[lc][i]+segt[rc][i];}
    }
    void putdown(int x){
        lazy[lc]+=lazy[x];    
        for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[lc][i];
        for(int i=0;i<=6;i++) segt[lc][i]=temp[i];
        lazy[rc]+=lazy[x];
        for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[rc][i];
        for(int i=0;i<=6;i++) segt[rc][i]=temp[i];
        lazy[x]=0;
    }
    
    void updata(int x,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) {
        for(int i=0;i<=6;i++) temp[(i+v)%7]=segt[x][i];
        for(int i=0;i<=6;i++) segt[x][i]=temp[i];
        lazy[x]+=v; return ; }
        if(lazy[x]) putdown(x);
        if(ql<=mid) updata(lc,l,mid,ql,qr,v);
        if(qr>mid) updata(rc,mid+1,r,ql,qr,v);
        for(int i=0;i<=6;i++) segt[x][i]=segt[lc][i]+segt[rc][i];
    }
    ll query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return segt[x][0];
        if(lazy[x]) putdown(x);
        if(qr<=mid) return query(lc,l,mid,ql,qr);
        else if(ql>mid) return query(rc,mid+1,r,ql,qr);
        return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);  
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&q);
        while(q--){
            scanf("%s%d%d",&qu,&xx,&yy);
            if(qu[0]=='a'){
            scanf("%d",&zz);
                updata(1,1,n,xx,yy,zz);
            }
            else printf("%lld
    ",query(1,1,n,xx,yy));
        }
        return 0;
    }
    codevs 线段树练习4
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    const int maxn=200050;
    typedef long long ll;
    char s[10];
    ll tmp,nn,qs,a,b,c,n,m;
    ll aa[maxn],sgt[maxn<<2],sgd[maxn<<2],sgx[maxn<<2],lzj[maxn<<2],lzc[maxn<<2];
    using namespace std;
    inline ll read(){
        ll ret=0,f=1; char ch=getchar();
        while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
        if(ch=='-') {f=-1;ch=getchar();}
        for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
        return ret*f;
    }
    void down(int x,int len,int l_len,int r_len){
         if(lzc[x]) {
         if(lzj[x]) tmp=(sgt[x]-lzj[x]*len)/len;
         else tmp=sgt[x]/len;
         sgt[lc]=tmp*l_len; lzc[lc]=1; lzj[lc]=0;
         sgd[lc]=sgx[lc]=tmp;
         sgt[rc]=tmp*r_len; lzc[rc]=1; lzj[rc]=0;
         sgd[rc]=sgx[rc]=tmp;
         lzc[x]=0; 
         }
         if(lzj[x]){
            sgt[lc]+=lzj[x]*l_len; lzj[lc]+=lzj[x];  
            sgt[rc]+=lzj[x]*r_len; lzj[rc]+=lzj[x]; 
            sgd[lc]+=lzj[x]; sgx[lc]+=lzj[x]; sgd[rc]+=lzj[x]; sgx[rc]+=lzj[x];
         lzj[x]=0;
         }
    }
    void build(int x,int l,int r){
        if(l==r) {sgd[x]=sgx[x]=sgt[x]=aa[l];return;}
        build(lc,l,mid); build(rc,mid+1,r);
        sgt[x]=sgt[lc]+sgt[rc];
        sgd[x]=max(sgd[lc],sgd[rc]);
        sgx[x]=min(sgx[lc],sgx[rc]);
    }
    void add(int x,int ql,int qr,int l,int r,int v,int cj){
        if(l>=ql&&r<=qr) {
            if(cj==1) {sgt[x]+=v*(r-l+1);  lzj[x]+=v; 
            sgd[x]+=v; sgx[x]+=v;
            }
            else {sgt[x]=v*(r-l+1);  lzc[x]=1; lzj[x]=0;
            sgd[x]=sgx[x]=v;
            }
            return;
        }
        if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid);
        if(ql<=mid) add(lc,ql,qr,l,mid,v,cj);
        if(qr>mid) add(rc,ql,qr,mid+1,r,v,cj);
        sgt[x]=sgt[lc]+sgt[rc];
        sgd[x]=max(sgd[lc],sgd[rc]);
        sgx[x]=min(sgx[lc],sgx[rc]);
    }
    ll query(int x,int ql,int qr,int l,int r,int cs){
        if(l>=ql&&r<=qr) 
        {if(cs==1) return sgd[x];
         if(cs==2) return sgx[x];
         if(cs==3) return sgt[x];
        }
        if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid);
        if(qr<=mid) return query(lc,ql,qr,l,mid,cs);
        else if(ql>mid) return query(rc,ql,qr,mid+1,r,cs);
        else {if(cs==3)return query(lc,ql,qr,l,mid,cs)+query(rc,ql,qr,mid+1,r,cs);
              if(cs==1) return max(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs));
              if(cs==2) return min(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs));
        }
    }
    int main()
    {
        n=read(); m=read();
        for(int i=1;i<=n;i++) aa[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;i++){
         scanf("%s",&s); a=read();b=read();
         if(s[0]=='a') add(1,a,b,1,n,read(),1);
         else if(s[1]=='e') add(1,a,b,1,n,read(),2);
         else if(s[1]=='a') printf("%lld
    ",query(1,a,b,1,n,1));
         else if(s[1]=='i') printf("%lld
    ",query(1,a,b,1,n,2));
         else printf("%lld
    ",query(1,a,b,1,n,3));
       }
       return 0;
    }
    codevs 线段树练习5

     

    2.树状数组

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int maxn=500000+5;
    int n,m,x,y,k,c[maxn];
    int lowbit(int x){
        return x&(-x);
    } 
    void add(int x,int v){
        for(int i=x;i<=n;i=i+lowbit(i)) c[i]+=v; 
    }
    int sum(int x){
        int ans=0;
        for(int i=x;i>=1;i=i-lowbit(i)) ans+=c[i];
        return ans;
    }
    int main()
    {
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
       {
            scanf("%d",&x);
            add(i,x);
       } 
       while(m--){
           scanf("%d%d%d",&k,&x,&y);
           if(k==1) add(x,y);
           else  printf("%d
    ",sum(y)-sum(x-1));
       }
       return 0;
    }
    洛谷 树状数组
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=500000+5;
    using namespace std;
    int n,m,x,y,k,v,tmp,c[maxn]; 
    int lowbit(int x){
        return x&(x^(x-1));
    }
    void add(int x,int v){
        for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v;
    }
    int sum(int x){
        int ans=0;
        for(int i=x;i>0;i-=lowbit(i)) ans+=c[i];
        return ans;
    }
    int main()
    {
       ios::sync_with_stdio(false);
       cin>>n>>m;
       for(int i=1;i<=n;i++){
           cin>>x;
           add(i,x-tmp);
           tmp=x;
       }
       while(m--){
           cin>>k>>x;
           if(k==1){
               cin>>y>>v;
               add(x,v);
               add(y+1,-v);
           }
        else{
           cout<<sum(x)<<endl;
        } 
       }
       return 0;
    }
    洛谷 树状数组2 差分
    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=100007;
    typedef long long LL; 
    using namespace std;
    int T,ls[N],sum[N],q[N][2];
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int hash(int x) {return lower_bound(ls+1,ls+ls[0]+1,x)-ls;}
    
    void add(int x,int v) {
        for(int i=x;i<=ls[0];i+=(i&(-i)))
             sum[i]+=v;
    }
    
    int qry(int x) {
        int res=0;
        for(int i=x;i;i-=(i&(-i))) 
            res+=sum[i];
        return res;
    }
    
    void kth(int k) {
        int res=0;
        for(int i=20;i>=0;i--) {
            res+=(1<<i);
            if(res>=ls[0]||sum[res]>=k) res-=(1<<i);
            else k-=sum[res];
        }
        printf("%d
    ",ls[res+1]);
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    #endif
        read(T);
        for(int i=1;i<=T;i++) {
            read(q[i][0]); read(q[i][1]);
            if(q[i][0]!=4) ls[++ls[0]]=q[i][1];
        }
        sort(ls+1,ls+ls[0]+1);
        int tpsz=unique(ls+1,ls+ls[0]+1)-(ls+1); ls[0]=tpsz;
        for(int i=1;i<=T;i++) {
            switch(q[i][0]) {
                case 1:add(hash(q[i][1]),1);break;
                case 2:add(hash(q[i][1]),-1);break;
                case 3:printf("%d
    ",qry(hash(q[i][1])-1)+1);break;
                case 4:kth(q[i][1]);break;
                case 5:kth(qry(hash(q[i][1])-1));break;
                case 6:kth(qry(hash(q[i][1]))+1);break;
            }
        }
        return 0;
    }
    数状数组普通平衡树

    3.ZKW线段树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=200005;
    int m=1,x,y,T,n,a[maxn<<2];
    char q[10];
    using namespace std;
    void build(){
        for(;m<=n+1;m<<=1);
        for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]);
        for(int i=m-1;i>0;i--) a[i]=a[i<<1]+a[i<<1|1];
    }
    void add(int x,int v){
        int k=x+m; a[k]+=v;
        for(k>>=1;k;k>>=1) a[k]=a[k<<1]+a[k<<1|1];
    }
    int query(int l,int r){
        int ret=0;
        for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){
            if(~i&1) ret+=a[i^1];
            if(j&1) ret+=a[j^1];
        }
        return ret;
    }
    int main()
    {
       scanf("%d",&T);
       for(int t=1;t<=T;t++){
           scanf("%d",&n);
        cout<<"Case "<<t<<":"<<endl;
           build();
           for(;;){
               scanf("%s",&q);
               if(q[0]=='E') break;
               scanf("%d%d",&x,&y);
               if(q[0]=='A') add(x,y);
               else if(q[0]=='S') add(x,-y);
               else printf("%d
    ",query(x,y));
           }
           m=1;memset(a,0,sizeof(a));
       }
       return 0;
    }
    zkw线段树 sum
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=200005;
    int f,m=1,x,y,T,n,a[maxn<<2];
    char q[5];
    using namespace std;
    void build(){
        for(;m<=n+1;m<<=1);
        for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]);
        for(int i=m-1;i>0;i--) a[i]=max(a[i<<1],a[i<<1|1]);
    }
    void add(int x,int v){
        int k=x+m; a[k]=v;
        for(k>>=1;k;k>>=1) a[k]=max(a[k<<1],a[k<<1|1]);
    }
    int query(int l,int r){
        int ret=0;
        for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){
            if(~i&1) ret=max(ret,a[i^1]);
            if(j&1) ret=max(ret,a[j^1]);
        }
        return ret;
    }
    int main()
    {
       while(scanf("%d%d",&n,&f)!=EOF){
           build();
           while(f--){
               scanf("%s%d%d",&q,&x,&y);
               if(q[0]=='U') add(x,y);
               else printf("%d
    ",query(x,y));
           }
           m=1;memset(a,0,sizeof(a));
       }
       return 0;
    }
    zkw线段树 max

     

    4.ST表

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=1e6+299;
    using namespace std;
    int n,m,l,r,st[maxn][20];
    void make_st(){
        for(int j=1;j<=20;j++)
          for(int i=1;i+(1<<j)-1<=n;i++)
            st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    }
    int query(int l,int r){
        int k=0;
        while(l+(1<<k)-1<=r) k++;
        if(k) k--;
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&st[i][0]);
        make_st();
        while(m--){
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(l,r)); 
        }
        return 0;
    }
    st表

     

    5.可持久化线段树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=100005;
    int sz,T,n,m,rt[maxn],tot,lc[maxn*20],rc[maxn*20],sum[maxn*20],a[maxn],b[maxn];
    using namespace std;
    void update(int &o,int l,int r,int last,int v){
        o=++tot;
        lc[o]=lc[last];
        rc[o]=rc[last];
        sum[o]=sum[last]+1;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(v<=mid) update(lc[o],l,mid,lc[last],v);
        else update(rc[o],mid+1,r,rc[last],v);
    }
    int query(int ql,int qr,int l,int r,int k){
        if(l==r) return l;    
        int mid=(l+r)>>1;
        int cnt=sum[lc[qr]]-sum[lc[ql]];
        if(cnt>=k) return query(lc[ql],lc[qr],l,mid,k);
        else return query(rc[ql],rc[qr],mid+1,r,k-cnt);
    }
    int main()
    {
         scanf("%d%d",&n,&m);
         for(int i=1;i<=n;i++) { scanf("%d",&a[i]);b[i]=a[i];}
         sort(b+1,b+n+1);
         sz=unique(b+1,b+n+1)-(b+1);
         tot=0;
         rt[0]=++tot;
         //build(rt[0],1,sz);
         for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+sz+1,a[i])-b; 
         for(int i=1;i<=n;i++) update(rt[i],1,sz,rt[i-1],a[i]);
         for(int i=1;i<=m;i++){
           int l,r,k;scanf("%d%d%d",&l,&r,&k);
           printf("%d
    ",b[query(rt[l-1],rt[r],1,sz,k)]);
         } 
       return 0;
    }
    主席树

     

    6.树链剖分

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define rc x<<1|1
    #define lc x<<1
    #define mid ((l+r)>>1)
    using namespace std;
    const int maxn=150005;
    int x,y,z,k,n,q,s,mod,w[maxn],fir[maxn],next[maxn*2],to[maxn*2],father[maxn],R[maxn],size[maxn],tid[maxn];
    int top[maxn],e[maxn],in[maxn],segt[maxn<<2],lazy[maxn<<2];
    int ecnt,tot;
    inline void add(int u,int v){
        next[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;in[u]++;
        next[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;in[v]++;
    }
    void down(int x,int l_len,int r_len){
        if(l_len) lazy[lc]+=lazy[x]%mod, segt[lc]+=l_len*lazy[x]%mod;
        if(r_len) lazy[rc]+=lazy[x]%mod, segt[rc]+=r_len*lazy[x]%mod;
        lazy[x]=0;
    }
    void change(int x,int l,int r,int ql,int qr,int v){
        if(l>=ql&&r<=qr) {segt[x]+=v*(r-l+1);lazy[x]+=v;lazy[x]%=mod;return;}    
        if(lazy[x]) down(x,mid-l+1,r-mid);
        if(ql<=mid) change(lc,l,mid,ql,qr,v);
        if(qr>mid) change(rc,mid+1,r,ql,qr,v);
        segt[x]=(segt[lc]+segt[rc])%mod;    
    }
    int query(int x,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr) return segt[x];
        if(lazy[x]) down(x,mid-l+1,r-mid);
        if(qr<=mid) return query(lc,l,mid,ql,qr)%mod;
        if(ql>mid) return query(rc,mid+1,r,ql,qr)%mod;
        return (query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr))%mod;
    }
    void dfs(int x,int fa){
        father[x]=fa;R[x]=R[fa]+1;size[x]=1;
        for(int i=fir[x];i;i=next[i]){
            if(to[i]!=fa){
                dfs(to[i],x);
                size[x]+=size[to[i]];
                }
        }
    }
    void dfs2(int x){
        tid[x]=++tot;
        change(1,1,n,tot,tot,w[x]);
        int mson=0;
        if(in[x]==1&&x!=s){
            e[x]=x;
            return;
        }
        for(int i=fir[x];i;i=next[i])
        if(size[to[i]]<size[x]&&size[to[i]]>size[mson]) mson=to[i];
        top[mson]=top[x];
        dfs2(mson); e[x]=e[mson];
        for(int i=fir[x];i;i=next[i]){
            if(size[to[i]]<size[x]&&to[i]!=mson){
                top[to[i]]=to[i];
                dfs2(to[i]);
                e[x]=e[to[i]];
            }
        }
    }
    
    void schange(int x,int y,int z){
        while(top[x]!=top[y]){
            if(R[top[x]]<R[top[y]]) swap(x,y);
            change(1,1,n,tid[top[x]],tid[x],z);
            x=father[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        change(1,1,n,tid[x],tid[y],z);
    }
    
    int squery(int x,int y){
        int ret=0;
        while(top[x]!=top[y]){
            if(R[top[x]]<R[top[y]]) swap(x,y);
            ret+=query(1,1,n,tid[top[x]],tid[x]); ret=ret%mod;
            x=father[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        ret+=query(1,1,n,tid[x],tid[y]); ret=ret%mod;
        return ret;
    }
    
    int main()
    {
       scanf("%d%d%d%d",&n,&q,&s,&mod);
       for(int i=1;i<=n;i++) scanf("%d",&w[i]);
       for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
       } 
       father[s]=s;top[s]=s;
       dfs(s,s);dfs2(s);
       for(int i=1;i<=q;i++){
           scanf("%d",&k);
           if(k==1){
               scanf("%d%d%d",&x,&y,&z);
               schange(x,y,z);
           
        }
        else if(k==2){
            scanf("%d%d",&x,&y);
               printf("%d
    ",squery(x,y));
        }
        else if(k==3){
            scanf("%d%d",&x,&z);
            change(1,1,n,tid[x],tid[e[x]],z);
        }
        else{
            scanf("%d",&x);
            printf("%d
    ",query(1,1,n,tid[x],tid[e[x]]));
        }
       }
       return 0;
    }
    树链剖分

     

    7.treap

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<set>
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    const int N=200007;
    typedef long long LL; 
    typedef double db;
    using namespace std;
    int T,o,x;
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int rt,tot,l[N],r[N],v[N],hr[N],sz[N];
    #define lc l[x]
    #define rc r[x]
    void update(int x) { sz[x]=sz[lc]+sz[rc]+1; }
    
    void left(int &x) {
        int y=r[x];
        r[x]=l[y];
        l[y]=x;
        update(x);
        x=y;
        update(y);
    }
    
    void right(int &x) {
        int y=l[x];
        l[x]=r[y];
        r[y]=x;
        update(x);
        x=y;
        update(y);
    }
    
    void insert(int &x,int y) {
        if(!x) {
            x=++tot;
            v[x]=y;
            hr[x]=rand();
            sz[x]=1;
            l[x]=r[x]=0;
            return;
        }
        if(y<=v[x]) {
            insert(lc,y);
            if(hr[lc]>hr[x]) right(x);
        }
        else {
            insert(rc,y);
            if(hr[rc]>hr[x]) left(x);
        }
        update(x);
    }
    
    void del(int &x,int y) {
        if(!x) return;
        if(v[x]==y) {
            if(!lc) x=rc;
            else if(!rc) x=lc;
            else {
                if(hr[lc]>hr[rc]) {
                    right(x); del(rc,y);
                }
                else {
                    left(x); del(lc,y);
                }
                update(x);
            }
        }
        else {
            if(y<v[x]) del(lc,y);
            else del(rc,y);    
            update(x);
        }
    }
    
    int rak(int rt,int y) {
        int rs=1;
        for(int x=rt;x;) {
            if(v[x]<y) rs+=sz[lc]+1,x=rc;
            else x=lc;
        }
        return rs;
    }
    
    int kth(int rt,int k) {
        for(int x=rt;x;) {
            if(sz[lc]+1==k) return v[x];
            if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
            else x=lc;
        }
        return -1;
    }
    
    int pre(int rt,int y) {
        int rs=-1;
        for(int x=rt;x;) {
            if(v[x]<y) rs=v[x],x=rc;
            else x=lc;
        }
        return rs;
    }
    
    int nxt(int rt,int y) {
        int rs=-1;
        for(int x=rt;x;) {
            if(v[x]>y) rs=v[x],x=lc;
            else x=rc;
        }
        return rs;
    }
    
    int main() {
    #ifdef DEBUG
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    #endif
        srand(998244353);
        read(T);
        while(T--) {
            read(o); read(x);
            switch(o) {
                case 1:insert(rt,x);break;
                case 2:del(rt,x);break;
                case 3:printf("%d
    ",rak(rt,x));break;
                case 4:printf("%d
    ",kth(rt,x));break;
                case 5:printf("%d
    ",pre(rt,x));break;
                case 6:printf("%d
    ",nxt(rt,x));break;
            }
        }
        return 0;
    }
    treap
    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    const int N=100007;
    typedef long long LL;
    using namespace std;
    int T,rt;
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    int n,v[N],hr[N],l[N],r[N],sz[N],tot;
    #define lc l[x]
    #define rc r[x]
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    
    int merge(int x,int y) {
        if(!(x*y)) return x^y;
        if(hr[x]<hr[y]) rc=merge(rc,y);
        else {
            swap(x,y);
            lc=merge(y,lc);
        }
        update(x);
        return x; 
    }
    
    #define pr pair<int,int>
    #define se second
    #define fi first
    pr split(int x,int k) {
        if(!x) return make_pair(0,0);
        pr p;
        if(sz[lc]>=k) {
            p=split(lc,k);
            lc=p.se; p.se=x;
        }
        else {
            p=split(rc,k-sz[lc]-1);
            rc=p.fi; p.fi=x;  
        }
        update(x);
        return p;
    }
    
    int cre(int y) {
        int x=++tot;
        hr[x]=rand();
        v[x]=y;
        sz[x]=1;
        return x;
    }
    
    int rank(int y) {
        int res=1;
        for(int x=rt;x;) {
            if(v[x]<y) res+=(sz[lc]+1),x=rc;
            else x=lc;
        }
        return res;
    }
    
    int kth(int k) {
        int res=-1;
        for(int x=rt;x;) {
            if(sz[lc]+1==k) return v[x];
            if(sz[lc]+1>k) x=lc;
            else k-=(sz[lc]+1),x=rc;
        }
    }
    
    int pre(int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]<y) res=v[x],x=rc;
            else x=lc;
        }
        return res;
    }
    
    int nxt(int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]>y) res=v[x],x=lc;
            else x=rc;    
        }
        return res;
    }
    
    void insert(int x,int y) {
        int z=cre(y);
        int k=rank(y);
        pr p=split(x,k-1);
        rt=merge(p.fi,z);
        rt=merge(rt,p.se);
    }
    
    void del(int x,int y) {
        int k=rank(y);
        pr p=split(x,k-1);
        pr q=split(p.se,1);
        rt=merge(p.fi,q.se);
    }
    
    int main() {
        srand(time(0));
        read(T);
        while(T--) {
            int o,x;
            read(o); read(x);
            switch(o) {
                case 1:insert(rt,x);break;
                case 2:del(rt,x);break;
                case 3:printf("%d
    ",rank(x));break;
                case 4:printf("%d
    ",kth(x));break;
                case 5:printf("%d
    ",pre(x));break;
                case 6:printf("%d
    ",nxt(x));break;
            }
        }
        return 0;
    }
    非旋treap
    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    const int N=100007;
    typedef long long LL;
    using namespace std;
    int rt,n,m,tot,ch[N][2],hr[N],sz[N],flip[N];
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    #define lc ch[x][0]
    #define rc ch[x][1]
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    
    int build(int l,int r) {
        if(l>r) return 0;
        int mid=((l+r)>>1);
        int tplc=build(l,mid-1);
        int x=++tot; 
        hr[x]=rand();
        lc=tplc;
        rc=build(mid+1,r);
        update(x);
        return x;
    }
    
    void down(int x) {
        if(!flip[x]) return;
        swap(lc,rc);
        if(lc) flip[lc]^=1;
        if(rc) flip[rc]^=1;
        flip[x]^=1;
    }
    
    #define pr pair<int,int>
    #define fi first
    #define se second
    pr split(int x,int k) {
        if(!x) return make_pair(0,0);
        pr p;
        down(x);
        if(sz[lc]>=k) {
            p=split(lc,k);
            lc=p.se; p.se=x;
        }
        else {
            p=split(rc,k-sz[lc]-1);
            rc=p.fi; p.fi=x;
        }
        update(x);
        return p;
    }
    
    int merge(int x,int y) {
        if(!(x*y)) return x^y;
        if(hr[x]<hr[y]) {
            down(x);
            rc=merge(rc,y);
        }
        else {
            swap(x,y);
            down(x);
            lc=merge(y,lc);
        }
        update(x);
        return x;
    } 
    
    void rever(int l,int r) {
        pr p=split(rt,l-1);
        pr q=split(p.se,r-l+1);
        flip[q.fi]^=1;
        rt=merge(merge(p.fi,q.fi),q.se);
    }
    
    void print(int x) {
        down(x);
        if(lc) print(lc);
        printf("%d ",x);
        if(rc) print(rc);
    }
    
    int main() {
        srand(time(0)); 
        read(n); read(m);
        rt=build(1,n);
        while(m--) {
            int l,r;
            read(l); read(r);
            rever(l,r);
        }
        print(rt);
        return 0;
    }
    非旋treap文艺平衡树

    8.splay

    //Twenty 
    #include <cstdio>
    #define Maxn 1000000
    using namespace std;
    int f[Maxn];
    int ch[Maxn][2];
    int key[Maxn];
    int cnt[Maxn];
    int siz[Maxn];
    int sz,root;
    void clear(int x) {
        ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0;
    }
    int getson(int x) {return ch[f[x]][1]==x;}
    void update(int x) {
        siz[x]=cnt[x];
        if (ch[x][0]) siz[x]+=siz[ch[x][0]];
        if (ch[x][1]) siz[x]+=siz[ch[x][1]];
    }
    int rotate(int x) {
        int fa=f[x],fafa=f[fa],k=getson(x);
        ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa;
        ch[x][k^1]=fa;f[fa]=x;f[x]=fafa;
        if (fafa)
            ch[fafa][ch[fafa][1]==fa]=x;
        update(fa);update(x);
    }
    void splay(int x) {
        for (int fa;fa=f[x];rotate(x))
            if (f[fa])
                rotate(getson(x)==getson(fa) ? fa : x);
        root=x;
    }
    int pre() {
        int now=ch[root][0];
        while(ch[now][1])
            now=ch[now][1];
        return now;
    }
    int nex() {
        int now=ch[root][1];
        while(ch[now][0])
            now=ch[now][0];
        return now;
    }
    int findpos(int v) {
        int now=root,ans=0;
        while(1) {
            if (v<key[now])
                now=ch[now][0];
            else {
                ans+=ch[now][0]?siz[ch[now][0]]:0;
                if (v==key[now]) {
                    splay(now);
                    return ans+1;
                }
                ans+=cnt[now];
                now=ch[now][1];
            }
        }
    }
    int findx(int x) {
        int now=root;
        while(1) {
            if (ch[now][0] && x<=siz[ch[now][0]])
                now=ch[now][0];
            else {
                int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
                if (x<=temp)
                    return key[now];
                x-=temp;
                now=ch[now][1];
            }
        }
    }
    void create(int v) {
        sz++;
        ch[sz][0]=ch[sz][1]=f[sz]=0;
        key[sz]=v;
        cnt[sz]=1;
        siz[sz]=1;
    }
    void insert(int v) {
        if (!root)
            create(v),root=sz;
        else {
            int now=root,fa=0;
            while(1) {
                if (key[now]==v) {
                    cnt[now]++;
                    splay(now);
                    break;
                }
                fa=now;
                now=ch[fa][v>key[fa]];
                if (!now) {
                    create(v);
                    f[sz]=fa;
                    ch[fa][v>key[fa]]=sz;
                    update(fa);
                    splay(sz);
                    break;
                }
            }
        }
    }
    void del(int x) {
        int t=findpos(x);
        if (cnt[root]>1) {
            cnt[root]--;
            update(root);
            return;
        }
        if (!ch[root][0] && !ch[root][1]) {
            clear(root);
            root=0;
            return;
        }
        if (!ch[root][1]) {
            int temp=root;
            root=ch[root][0];
            f[root]=0;
            clear(temp);
            return;
        }
        else
        if (!ch[root][0]) {
            int temp=root;
            root=ch[root][1];
            f[root]=0;
            clear(temp);
            return;
        }
        int pre1=pre(),temp=root;
        splay(pre1);
        f[ch[temp][1]]=root;
        ch[root][1]=ch[temp][1];
        clear(temp);
        update(root);
    }
    int main()
    {  
        int n,opt,x;  
        scanf("%d",&n);  
        for (int i=1;i<=n;++i) {  
            scanf("%d%d",&opt,&x);  
            switch(opt) {  
                case 1: insert(x); break;  
                case 2: del(x); break;  
                case 3: printf("%d
    ",findpos(x)); break;  
                case 4: printf("%d
    ",findx(x)); break;  
                case 5: insert(x); printf("%d
    ",key[pre()]); del(x); break;
                case 6: insert(x); printf("%d
    ",key[nex()]); del(x); break;
            }  
        }  
    }   
    splay
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc ch[x][0]
    #define rc ch[x][1]
    using namespace std;
    const int maxn=100005;
    int n,T,l,r,root,cnt,flip[maxn],ch[maxn][2],p[maxn],sz[maxn];
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;} 
    void down(int x){
        if(!flip[x]) return;
        swap(lc,rc);
        flip[lc]^=1;flip[rc]^=1;
        flip[x]=0;
    }
    int kth(int x,int a){
        for(;x;){
        down(x);
        int k=sz[lc]+1;
        if(k==a) return x;
        if(k<a) a-=k,x=rc;
        else x=lc;
        }
    }
    void rotate(int x){
         int y=p[x],z=p[y];
         if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
         l=(x==ch[y][1]),r=l^1;
         ch[y][l]=ch[x][r]; p[ch[y][l]]=y;
         ch[x][r]=y; p[y]=x;
         update(y);
         update(x);
    }
    void splay(int x,int FA){
        if(p[x]!=FA){
            static int s[maxn],top=0;
          for(int i=x;i;i=p[i]) s[++top]=i;
          while(top) down(s[top--]);
        }
        for(;p[x]!=FA;rotate(x)){
           int y=p[x],z=p[y];
           if(z!=FA){
               ((ch[z][1]==y)^(ch[y][1]==x))?rotate(x):rotate(y);
           }
        }
        if(!FA) root=x;
    }
    void rever(int l,int r){
        l=kth(root,l);r=kth(root,r+2);
        splay(l,0);
        splay(r,l);
        int x=ch[root][1];
        flip[lc]^=1;
        int now=ch[r][0];
        ch[r][0]=0;
        update(r);
        update(root);
        x=kth(root,n-sz[now]+1);
        splay(x,0);
        x=rc; lc=now; update(x); update(root);
    }    
    int build(int n){
        if(!n) return 0;
        l=build(n>>1);
        int x=++cnt;
        lc=l;
        r=build(n-(n>>1)-1);
        rc=r;
        if(lc) p[lc]=x;
        if(rc) p[rc]=x;
        update(x);
        return x;
    }
    void print(int x){
        if(!x) return;
        down(x);
        print(lc);
        if(x>=2&&x<=n+1) printf("%d ",x-1);
        print(rc);
    }
    int main()
    {
       scanf("%d%d",&n,&T);
       root=build(n+2);
       while(T--){
            scanf("%d%d",&l,&r);
            rever(l,r);
       }
       print(root);
       return 0;
    }
    文艺平衡树
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc ch[x][0]
    #define rc ch[x][1]
    using namespace std;
    const int maxn=100005;
    int aa,bb,tot,root,n,m,ch[maxn][2],p[maxn],flip[maxn],sz[maxn];
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    void down(int x){
      if(!flip[x]) return;
      swap(lc,rc);
      flip[x]^=1;
      flip[lc]^=1;
      flip[rc]^=1;
    }
    void rotate(int x){
        int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
        if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
        ch[y][l]=ch[x][r]; p[ch[y][l]]=y;
        ch[x][r]=y; p[y]=x;
        update(y); update(x);
    }
    void splay(int x,int FA){
       if(p[x]==FA) return;
       static int s[maxn],top;
       for(int i=x;i;i=p[i]) s[++top]=i;
       while(top) down(s[top--]);
       for(;p[x]!=FA;rotate(x)){
         int y=p[x],z=p[y];
         if(z!=FA){
           ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
         }
       }
       if(FA==0) root=x;
    } 
    int build(int n){
       if(!n) return 0;
       int ll=build(n>>1);
       int x=++tot;
       lc=ll;
       rc=build(n-(n>>1)-1);
       if(lc) p[lc]=x;
       if(rc) p[rc]=x;
       update(x);
       return x;
    }
    int kth(int k){
        for(int x=root;x;){
           down(x);
           if(sz[lc]+1==k) return x;
           if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
           else x=lc;
        }
    }
    void print(int x){
      if(!x) return;
      down(x);
      print(lc);
      if(x>1&&x<n+2) printf("%d
    ",x-1);
      print(rc);
    }
    void rever(int l,int r){
        int ll=kth(l),rr=kth(r+2);
        //print(root);
        splay(ll,0); splay(rr,ll);
        flip[ch[rr][0]]^=1;
        int now=ch[rr][0];
        ch[rr][0]=0;
        update(rr);
        update(root);
        int x=kth(n-sz[now]+1);
        splay(x,0);
        x=rc; lc=now; p[now]=x; update(x); update(root);
    }
    
    int main()
    {
       scanf("%d%d",&n,&m);
       root=build(n+2); 
       while(m--){
        scanf("%d%d",&aa,&bb);
        rever(aa,bb);
       }
       print(root);
       return 0;
    }
    文艺平衡树加强
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<ctime>
    #define lc ch[x][0]
    #define rc ch[x][1]
    typedef long long LL;
    const int maxn=100000+299;
    using namespace std;
    int tt,root,tot,T,op,x,sz[maxn],ch[maxn][2],v[maxn],cnt[maxn],p[maxn];
    inline int read() {
        char ch=getchar(); int f=1,ret=0;
        while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
        return ret*f;
    }
    void update(int x) {sz[x]=sz[lc]+sz[rc]+cnt[x];}
    void rotate(int x) {
        int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
        if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
        ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
        ch[x][r]=y; p[y]=x;
        update(y); update(x);
    }
    void splay(int x) {
        if(x==root) return;
        for(;p[x];rotate(x)) {
            int y=p[x],z=p[y];
            if(z) (y==ch[z][1])^(x==ch[y][1])?rotate(x):rotate(y);
        }
        root=x;
    }
    void build(int &x,int y) {
        x=++tot;
        sz[x]=cnt[x]=1;
        v[x]=y;
        lc=rc=0;
    }
    int insert(int x,int y) {
        int res=0;
        if(!root) {build(root,y); return root;}
        if(v[x]==y) {cnt[x]++; res=x;}
        if(v[x]<y) {
            if(rc) res=insert(rc,y);
            else {build(rc,y); p[rc]=x; res=rc;}    
        }
        if(v[x]>y) {
            if(lc) res=insert(lc,y);
            else {build(lc,y); p[lc]=x; res=lc;}
        }
        update(x);
        return res;
    }
    int rank(int y) {
        int res=1;
        for(int x=root;x;) {
            if(v[x]==y) {
                splay(x); return sz[lc]+1;
            }
            if(v[x]>y) x=lc;
            else x=rc;
        }
    }
    int kth(int k) {
        int res=0;
        for(int x=root;x;) {
            if(sz[lc]+1<=k&&sz[lc]+cnt[x]>=k) return v[x];
            if(sz[lc]+1>k) x=lc;
            else k-=(sz[lc]+cnt[x]),x=rc;
        }
    }
    int pre(int y) {
        int x=root; x=lc;
        while(rc) {
            x=rc;
        }
        return x;
    }
    int nxt(int y) {
        int x=root; x=rc;
        while(lc) {
            x=lc;
        }
        return x;
    }
    void del(int x,int y) {
        if(!x) return;
        for(;;) {
            if(!x) return;
            int fa=0;
            if(v[x]==y) {
                splay(x);
                if(cnt[x]>1) cnt[x]--;
                else if(!lc) {if(rc) p[rc]=fa; root=rc;}
                else if(!rc) {if(lc) p[lc]=fa; root=lc;}
                else {
                    int z=pre(x),tp;
                    splay(z);
                    tp=ch[ch[root][1]][1];
                    ch[root][1]=tp;
                    p[tp]=root;
                    update(root);
                 }
                 update(x);
                 return;
            }
            fa=x;
            if(v[x]<y) x=rc;
            else x=lc;  
        }
    }
    int main()
    {
        T=read();
        while(T--) {
            op=read(); x=read();
            switch(op){
            case 1:x=insert(root,x);splay(x);break;
            case 2:del(root,x);break;
            case 3:printf("%d
    ",rank(x));break;
            case 4:printf("%d
    ",kth(x));break;
            case 5:tt=insert(root,x);splay(tt);printf("%d
    ",v[pre(x)]);del(root,x);break;
            case 6:tt=insert(root,x);splay(tt);printf("%d
    ",v[nxt(x)]);del(root,x);break;
            }
        }
        return 0;
    }
    普通平衡树

     ---------------------------------------------------------------------

    12.2更新

    改进后的比之前短又好看又跑得快的splay

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=100007;
    typedef long long LL;
    using namespace std;
    int T,o,xx;
    
    namespace RD{
        const int sz=1<<15|1;
        char ch,buf[sz],*l,*r;
        void gechar(char &c) {
            if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
            c = l==r?EOF:*l++;
        }
        template<typename T> void read(T &x) {
            gechar(ch); x=0; T f=1;
            while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
            if(ch=='-') f=-1,gechar(ch);
            for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
        }
    }
    
    int rt,tot,v[N],ch[N][2],f[N],sz[N];
    #define lc ch[x][0]
    #define rc ch[x][1]
    
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    
    void rotate(int x) {
        int y=f[x],z=f[y],l=(x==ch[y][1]),r=l^1;
        if(z) ch[z][y==ch[z][1]]=x; f[x]=z;
        ch[y][l]=ch[x][r]; f[ch[x][r]]=y;
        ch[x][r]=y; f[y]=x;
        update(y); update(x);
    }
    
    void splay(int &rt,int x,int FA) {
        if(f[x]==FA) return;
        for(;f[x]!=FA;rotate(x)) {
            int y=f[x],z=f[y];
            if(z!=FA) (x==ch[x][1])^(y==ch[z][1])?rotate(x):rotate(y);
        }
        if(!FA) rt=x;
    }
    
    int cre(int y) {
        int x=++tot;
        v[x]=y;
        sz[x]=1;
        return x;
    }
    
    void insert(int &rt,int y) {
        int fa=0,l=1;
        for(int x=rt;;) {
            if(!x) {
                x=cre(y);
                if(fa) ch[fa][l]=x;
                else rt=x;
                f[x]=fa;
                splay(rt,x,0);
                return;
            }  
            if(y<=v[x]) fa=x,x=lc,l=0;
            else fa=x,x=rc,l=1;
        }
    }
    
    int rank(int &rt,int y) {
        int res=1,tp=0;
        for(int x=rt;x;) {
            if(v[x]==y) tp=x,x=lc;
            else if(v[x]<y) res+=(sz[lc]+1),x=rc;
            else x=lc;
        }
        if(tp) splay(rt,tp,0);
        return res;
    }
    
    int kth(int &rt,int k) {
        for(int x=rt;x;) {
            if(sz[lc]+1==k) return x;
            if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
            else x=lc;
        }
    }
    
    int pre(int rt,int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]<y) res=v[x],x=rc;
            else x=lc;
        }
        return res;
    }
    
    int nxt(int rt,int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]>y) res=v[x],x=lc;
            else x=rc;
        }
        return res;
    }
    
    void del(int &rt,int x) {
        int tp=rank(rt,x);
        if(tp==1||tp==sz[rt]) {
            if(ch[rt][0]) rt=ch[rt][0],f[rt]=0;
            else rt=ch[rt][1],f[rt]=0;
        }
        else {
            int y=kth(rt,tp-1);
            splay(rt,y,0);
            int z=kth(rt,tp+1);
            splay(rt,z,y);
            f[ch[z][0]]=0; ch[z][0]=0;
            update(z); update(y);
        }
    }
    
    int main() {
    #ifdef DEBUG
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
        RD::read(T);
        while(T--) {
            RD::read(o);  RD::read(xx);
            switch(o) {
                case 1:insert(rt,xx);break;
                case 2:del(rt,xx);break;
                case 3:printf("%d
    ",rank(rt,xx));break;
                case 4:printf("%d
    ",v[kth(rt,xx)]);break;
                case 5:printf("%d
    ",pre(rt,xx));break;
                case 6:printf("%d
    ",nxt(rt,xx));break;
            }
        }
        return 0;
    }
    View Code

     12.4 替罪羊树

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath> 
    const int N=100007*20; 
    typedef long long LL;
    typedef double db;
    using namespace std;
    int T,o,xx,rt;
    
    namespace RD{
        const int sz=1<<15|1;
        char ch,buf[sz],*l,*r;
        void gechar(char &c) {
            if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
            c = l==r?EOF:*l++;
        }
        template<typename T> void read(T &x) {
            gechar(ch); x=0; T f=1;
            while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
            if(ch=='-') f=-1,gechar(ch);
            for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
        }
    }
    
    
    int tot,ch[N][2],p[N],v[N],sz[N],E[N];
    #define lc ch[x][0]
    #define rc ch[x][1]
    
    int update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    
    int bal(int x) {
        return 0.75*sz[x]>=(db)sz[lc]&&0.75*sz[x]>=(db)sz[rc];
    } 
    
    int findx(int y) {
        for(int x=rt;x;) {
            if(v[x]==y) return x;
            if(v[x]<y) x=rc;
            else x=lc;
        }
    }
    
    void tra(int x){
        if(lc) tra(lc);
        E[++E[0]]=x;
        if(rc) tra(rc);
    }
    
    int build(int l,int r) {
        if(l>r) return 0;
        int mid=(l+r)>>1;
        int x=E[mid];
        lc=build(l,mid-1); p[lc]=x;
        rc=build(mid+1,r); p[rc]=x;
        update(x);
        return x;
    }
    
    void rebuild(int x) {
        E[0]=0; tra(x);
        int y=p[x],z=build(1,E[0]);
        if(y) ch[y][x==ch[y][1]]=z; p[z]=y;
        if(x==rt) rt=z;
    }
    
    int cre(int y) {
        int x=++tot; 
        v[x]=y;
        sz[x]=1;
        return x;
    }
    
    void insert(int y) {
        int fa=0,l=1,z=cre(y);
        for(int x=rt;;) {
            if(!x) {
                x=z; p[x]=fa;
                if(fa) ch[fa][l]=x; 
                else rt=x;
                break;
            }
            sz[x]++;
            if(v[x]<y) fa=x,l=1,x=rc;
            else fa=x,l=0,x=lc;
        }
        int tp=0;
        for(int x=z;x;x=p[x]) if(!bal(x)) tp=x;
        if(tp) rebuild(tp);
    }
    
    void del(int x) {
        if(lc&&rc) {
            int y=lc;
            while(ch[y][1]) y=ch[y][1];
            v[x]=v[y];
            x=y;
        }
        int son=lc?lc:rc;
        p[son]=p[x]; 
        if(p[x]) ch[p[x]][x==ch[p[x]][1]]=son;
        else rt=son;
        for(int i=p[son];i;i=p[i]) sz[i]--;
    }
    
    int rank(int y) {
        int res=1;
        for(int x=rt;x;) {
            if(v[x]<y) res+=sz[lc]+1,x=rc;
            else x=lc;
        }     
        return res;
    }
    
    int kth(int y) {
        for(int x=rt;x;) {
            if(sz[lc]+1==y) return v[x];
            if(sz[lc]+1<y) y-=(sz[lc]+1),x=rc;
            else x=lc; 
        }
    }
    
    int pre(int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]<y) res=v[x],x=rc;
            else x=lc;
        }
        return res;
    }
    
    int nxt(int y) {
        int res=-1;
        for(int x=rt;x;) {
            if(v[x]>y) res=v[x],x=lc;
            else x=rc;
        }
        return res;
    }
    
    
    int main() {
        RD::read(T);
        while(T--) {
            RD::read(o); RD::read(xx);
            switch(o) {
                case 1:insert(xx);break;
                case 2:del(findx(xx));break;
                case 3:printf("%d
    ",rank(xx));break;
                case 4:printf("%d
    ",kth(xx));break;
                case 5:printf("%d
    ",pre(xx));break;
                case 6:printf("%d
    ",nxt(xx));break;
            }
        } 
        return 0;
    }
    View Code
    【2.in】
    20
    1 964673
    5 968705
    4 1
    3 964673
    5 965257
    1 915269
    1 53283
    3 964673
    3 53283
    3 53283
    1 162641
    5 973984
    1 948119
    2 915269
    2 53283
    6 959161
    1 531821
    1 967521
    2 531821
    1 343410
    
    【2.out】
    964673
    964673
    1
    964673
    3
    1
    1
    964673
    964673

    【3.in】
    50
    1 577793
    1 408221
    1 880861
    2 408221
    1 460353
    1 223489
    6 577713
    4 2
    5 889905
    2 880861
    1 100033
    1 73956
    1 22575
    5 583761
    6 571549
    1 812645
    4 3
    1 643621
    1 451623
    6 14895
    1 556691
    4 1
    1 225789
    2 22575
    1 632329
    3 73956
    1 316785
    5 101413
    4 11
    5 639414
    6 636353
    1 272382
    1 434049
    2 643621
    1 99617
    2 577793
    1 921581
    1 894033
    3 223489
    1 767367
    3 272382
    1 642721
    1 272033
    3 632329
    1 737721
    1 864513
    5 746457
    1 877545
    1 51097
    1 484817
    【3.out】
    577793
    460353
    880861
    577793
    577793
    100033
    22575
    22575
    1
    100033
    643621
    632329
    643621
    4
    6
    13
    737721

    9.LCT

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc ch[x][0]
    #define rc ch[x][1]
    const int maxn=3*1e5+5;
    using namespace std;
    int k,tot,n,m,a,b,p[maxn],ch[maxn][2],v[maxn],sum[maxn],flip[maxn];
    inline int read(){
      int ret=0,f=1; char ch=getchar();
      while((ch!='-')&&(ch<'0'||ch>'9')) ch=getchar();
      if(ch=='-') f=-1,ch=getchar();
      for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
      return ret*f;
    }
    void update(int x) {sum[x]=v[x]; if(lc)sum[x]^=sum[lc]; if(rc)sum[x]^=sum[rc];} 
    void down(int x){
        if(!flip[x]) return ;
        swap(lc,rc);
        flip[lc]^=1;
        flip[rc]^=1;
        flip[x]^=1;
    }
    bool isroot(int x) {return (ch[p[x]][0]!=x)&&(ch[p[x]][1]!=x);}
    void rotate(int x){
        int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
        if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
        ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
        ch[x][r]=y; p[y]=x;
        update(y); update(x);
    }
    void splay(int x){
        static int s[maxn],top;
        s[top=1]=x;
        for(int i=x;!isroot(i);i=p[i]) s[++top]=p[i];
        while(top) down(s[top--]);
        for(;!isroot(x);rotate(x)){
            int y=p[x],z=p[y];
            if(!isroot(y)){
             ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
            }
        }
    }
    void access(int x){
        for(int t=0;x;x=p[t=x]){
         splay(x);
         ch[x][1]=t;
         update(x);
        }
    }
    int findroot(int x){
      access(x);
      splay(x);
      while(lc) x=lc;
      return x;
    }
    bool lt(int a,int b){
      return findroot(a)==findroot(b);
    }
    void newroot(int x){
       access(x);
       splay(x);//fasdgggggggggggggggg
       flip[x]^=1;
    }
    void link(int a,int b){
        if(lt(a,b)) return;
        newroot(a);
        p[a]=b;
    }
    void del(int a,int b){
       newroot(a);//splay(a);
       access(b);
       //if(p[b]==a) ch[a][b==ch[a][1]]=0; 
       splay(b);//sdgadfffgaggggggggggfjdgfjhfghgf
       if(ch[b][0]==a) ch[b][0]=p[a]=0; 
    }
    void change(int a,int b){
       splay(a);//newroot(a);
       v[a]=b;
       update(a);
    } 
    void query(int a,int b){
      newroot(a);//splay(a);
      access(b);
      splay(b);//gdfgfgb gshfthhhhhhhhhhhhhhhhhhhhh
      printf("%d
    ",sum[b]);
    }
    int main()
    {
       n=read(); m=read();
       for(int i=1;i<=n;i++){
        a=read();
        v[i]=sum[i]=a;
       }
       while(m--){
        k=read(); a=read(); b=read();
        switch(k){
        case 0:query(a,b);break;
        case 1:link(a,b); break;
        case 2:del(a,b); break;
        case 3:change(a,b);break;
        }
       }
       return 0;
    }
    LCT

     

    10.左偏树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc ch[x][0]
    #define rc ch[x][1]
    const int maxn=100000+299;
    using namespace std;
    int n,m,k,x,y,ch[maxn][2],fa[maxn],v[maxn],bo[maxn],dis[maxn];
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    int merge(int x,int y){
        if(!x) {return y;}
        if(!y) {return x;}
        if(v[x]>v[y]) swap(x,y);
        fa[y]=x;
        rc=merge(rc,y);
        if(dis[rc]>dis[lc]) swap(lc,rc);
        if(!rc) dis[x]=0;
        else dis[x]=dis[rc]+1;
        return x;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&v[i]);
            fa[i]=i;
        }
        while(m--){
            scanf("%d%d",&k,&x);
            if(k==1){
            scanf("%d",&y);
                if(!bo[x]&&!bo[y]&&find(x)!=find(y))
                x=merge(find(x),find(y));
            }
            else{
                if(bo[x]) cout<<-1<<endl;
                else{
                x=find(x);
                printf("%d
    ",v[x]);
                fa[lc]=lc; fa[rc]=rc;
                if(lc&&rc) lc=merge(lc,rc);    
                if(lc) fa[x]=lc;
                else fa[x]=rc;
                lc=rc=0;     
                }
                bo[x]=1;
            }
        }
        return 0;
    }
    左偏树

     

    11.KD-Tree

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=500000+299;
    using namespace std;
    int ans=1e9+7,now,nowx,nowmax,nowmin,root,y,n,D,data[maxn][2][2],ch[maxn][2];
    struct node{
        int d[2];
        friend bool operator <(const node&A,const node&B){
            return A.d[D]<B.d[D];
        }
    }a[maxn],T;
    void update(int x){
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                data[x][i][j]=a[x].d[i];
        for(int i=0;i<2;i++)
           if(y=ch[x][i])
           for(int j=0;j<2;j++){
               data[x][j][0]=min(data[x][j][0],data[y][j][0]);
               data[x][j][1]=max(data[x][j][1],data[y][j][1]);
           }
    }
    int build(int l,int r,int k){
        if(l>r) return 0;
        int mid=(l+r)>>1;
        D=k;
        nth_element(a+l,a+mid,a+r+1);
        ch[mid][0]=build(l,mid-1,k^1);
        ch[mid][1]=build(mid+1,r,k^1);
        update(mid);
        return mid;
    }
    int max_dis(int x){
        if(!x) return -1e9;
        int res=0;
        for(int i=0;i<2;i++)
            res+=max(abs(T.d[i]-data[x][i][0]),abs(data[x][i][1]-T.d[i]));
        return res;
    }
    int dis(int x){
        return abs(a[x].d[0]-T.d[0])+abs(a[x].d[1]-T.d[1]);
    }
    int min_dis(int x){
        if(!x) return 1e9;
        int res=0;
        for(int i=0;i<2;i++)
        res+=max(T.d[i]-data[x][i][1],0);
        for(int i=0;i<2;i++)
        res+=max(data[x][i][0]-T.d[i],0);
        return res;
    }
    void qrymin(int x){
        if(!x) return;
        if(x!=nowx) nowmin=min(dis(x),nowmin);
        int lc=ch[x][0],rc=ch[x][1];
        int l=min_dis(lc);
        int r=min_dis(rc);
        if(l>r) {swap(lc,rc);swap(l,r);}
        if(lc&&l<nowmin) qrymin(lc);
        if(rc&&r<nowmin) qrymin(rc);
    }
    void qrymax(int x){
        if(!x) return;
        if(x!=nowx) nowmax=max(dis(x),nowmax);
        int lc=ch[x][0],rc=ch[x][1];
        int l=max_dis(lc);
        int r=max_dis(rc);
        if(l<r) {swap(lc,rc);swap(l,r);}
        if(lc&&l>nowmax) qrymax(lc);
        if(rc&&r>nowmax) qrymax(rc);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].d[0],&a[i].d[1]);
        root=build(1,n,0);
        for(int i=1;i<=n;i++){
            nowx=i;
            T=a[i]; 
            nowmax=-1e9+7; 
            nowmin=1e9+7;
            qrymin(root); 
            qrymax(root);
            ans=min(ans,nowmax-nowmin);
        }
        printf("%d
    ",ans);
       return 0;
    }
    KD-Tree

     

     12.分块

    //Twenty
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath> 
    #include<algorithm>
    const int maxn=200000+10;
    using namespace std;
    int n,m,k,gs,ks;
    int a[maxn],b[maxn],c[450][maxn],l,r,v;
    char qu[10];
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m>>k;
        ks=floor(sqrt(n));
        if(n%ks==0) gs=n/ks; else gs=n/ks+1;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=ks;i++)
        for(int j=1;j<=gs;j++)
        {
            int num=(i-1)*gs+j;
            c[i][a[num]%k]++;
        }
        while(m--){
            cin>>qu>>l>>r;
            int lx,rx,ans;
            ans=0;
            lx=(l-1)/gs+1;
            rx=(r-1)/gs;
            if(qu[0]=='c'){
               if(rx<lx)
                {for(int i=l;i<=r;i++)
                  if((a[i]+b[i])%k==0)ans++;}
               else {
                    for(int i=l;i<=lx*gs;i++)
                     if((a[i]+b[lx])%k==0)ans++;
                 for(int i=lx+1;i<=rx;i++)
                      ans+=c[i][(k-b[i]%k)%k];
                    for(int i=rx*gs+1;i<=r;i++)
                  if((a[i]+b[rx+1])%k==0)ans++;
                } 
                cout<<ans<<endl;            
            }
            else {
               cin>>v;
               if(rx<lx)
               {
                   for(int i=l;i<=r;i++)
                   {   
                    c[lx][a[i]%k]--;
                       a[i]+=v;
                       c[lx][a[i]%k]++;
                   }
               } 
               else {
                    for(int i=l;i<=lx*gs;i++)
                    {
                        c[lx][a[i]%k]--;
                       a[i]+=v;
                       c[lx][a[i]%k]++;
                    }
                    for(int i=lx+1;i<=rx;i++)
                      b[i]+=v;
                    for(int i=rx*gs+1;i<=r;i++)
                    {
                        c[rx][a[i]%k]--;
                       a[i]+=v;
                       c[rx][a[i]%k]++;
                    }
                }
            }
        } 
        return 0;
    }
    线段树4加强版(分块)

     

    13.树套树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    const int maxn=10005;
    bool st;
    int tot,T,ql,qr,qq,aa[maxn],n,m,sg[maxn<<2],ls[maxn*450],rs[maxn*450],sgq[maxn*450],que[maxn];
    int nn=1e9;
    char qs[5];
    bool ed;
    using namespace std;
    inline int read() {
     int res=0;char ch=getchar();
     while(ch<'0'||ch>'9') ch=getchar();
     for(;ch>='0'&&ch<='9';ch=getchar()) res=res*10+ch-'0';
     return res;
    }
    void buq(int &x,int l,int r,int v,int kk){
        if(!x) x=++tot;
        if(l==r) {if(kk) sgq[x]++; else sgq[x]--; return;}
        if(v<=mid) buq(ls[x],l,mid,v,kk);
        else buq(rs[x],mid+1,r,v,kk);
        sgq[x]=sgq[ls[x]]+sgq[rs[x]];
    }
    void build(int x,int l,int r){
        for(int i=l;i<=r;i++) buq(sg[x],1,nn,aa[i],1);
        if(l==r) return;
        build(lc,l,mid); build(rc,mid+1,r);
    }
    void change(int x,int l,int r,int xw,int jv,int xv){
        buq(sg[x],1,nn,jv,0); buq(sg[x],1,nn,xv,1);
        if(l==r) return;
        if(xw<=mid) change(lc,l,mid,xw,jv,xv);
        else change(rc,mid+1,r,xw,jv,xv);
    }
    void query(int x,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr) {que[++que[0]]=sg[x];return;}
        if(qr<=mid) query(lc,l,mid,ql,qr);
        else if(ql>mid) query(rc,mid+1,r,ql,qr);
        else {query(lc,l,mid,ql,qr); query(rc,mid+1,r,ql,qr);}
    }
    int qry(int ql,int qr,int k){
        que[0]=0;
        query(1,1,n,ql,qr);
        int l=1,r=nn;
        for(;;){
            int now=0;
            for(int i=1;i<=que[0];i++)
            now+=sgq[ls[que[i]]];
            if(now>=k) {
             for(int i=1;i<=que[0];i++)
              que[i]=ls[que[i]];
             r=mid;
            }
            else{
             for(int i=1;i<=que[0];i++)
              que[i]=rs[que[i]];
             k-=now;
             l=mid+1;
            }
            if(l==r) return l;
        }
    }
    int main()
    { 
        //printf("%d
    ",(&ed-&st)/1024/1024);
        //for(;;);
       //freopen("dynamic9.in","r",stdin);
       //freopen("aa.out","w",stdout);
       /*scanf("%d",&T);
       while(T--){*/
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) {aa[i]=read(); aa[i]++; }
        /*sort(aa+1,aa+n+1);
        nn=unique(aa+1,aa+n+1)-(aa+1);*/
        //for(int i=1;i<=n;i++) {bb[i]=lower_bound(aa+1,aa+n+1,bb[i])-aa;}
        build(1,1,n);
        while(m--){
          scanf("%s",qs);
           ql=read(); qr=read();
          if(qs[0]=='C'){
               qr++;
             change(1,1,n,ql,aa[ql],qr); 
             aa[ql]=qr;
          }
          else{
            qq=read();//scanf("%d",&qq);
            printf("%d
    ",qry(ql,qr,qq)-1);
          }
        }
        /*if(T){
        tot=0;
        memset(aa,0,sizeof(aa));
        memset(sg,0,sizeof(sg));
        memset(sgq,0,sizeof(sgq));
        memset(ls,0,sizeof(ls));
        memset(rs,0,sizeof(rs));
        }
       }*/
       return 0;
    }
    
    树套树
    线段树套权值线段树 带修改区间第k大
    //Twenty
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<ctime>
    #define inf 1e8+1 
    const int maxn=1e5+5;
    typedef long long LL;
    using namespace std;
    int n,T,a[maxn];
    
    template<typename T> void read(T &x) {
        char ch=getchar(); T f=1; x=0;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int tot,ls[maxn*100],rs[maxn*100],val[maxn*100];
    #define lc ls[x]
    #define rc rs[x] 
    #define mid ((l+r)>>1)
    
    int sqry(int x,int l,int r,int ql,int qr) {
        if(!x) return 0;
        if(l>=ql&&r<=qr) return val[x];
        if(qr<=mid) return sqry(lc,l,mid,ql,qr);
        else if(ql>mid) return sqry(rc,mid+1,r,ql,qr);
        return sqry(lc,l,mid,ql,qr)+sqry(rc,mid+1,r,ql,qr);
    }
    
    void update(int &x,int l,int r,int v,int f) {
        if(!x) x=++tot;
         if(l==r) {val[x]+=f; return;}
        if(v<=mid) update(lc,l,mid,v,f);
        else update(rc,mid+1,r,v,f);
        val[x]=val[lc]+val[rc];
    }
    
    int rt[maxn];
    void change(int x,int y,int o) {
        for(int i=x;i<=n;i+=(i&(-i))) {
            if(!o) update(rt[i],1,inf,a[x],-1);
            update(rt[i],1,inf,y,1);    
        }
        a[x]=y;
    }
    
    int qry(int l,int r,int ql,int qr) {
        int res1=0,res2=0;
        for(int i=r;i;i-=(i&(-i))) 
            res1+=sqry(rt[i],1,inf,ql,qr);
        for(int i=l-1;i>0;i-=(i&(-i))) 
            res2+=sqry(rt[i],1,inf,ql,qr);
        return res1-res2;
    }
    
    int q1[maxn],h=1,t,q2[maxn],hh=1,tt;
    int kth(int l,int r,int k) {
        h=hh=1; t=tt=0; 
        int res=0;
        for(int i=r;i;i-=(i&(-i))) 
            if(rt[i]&&val[rt[i]]) q1[++t]=rt[i];
        for(int i=l-1;i>0;i-=(i&(-i))) 
            if(rt[i]&&val[rt[i]]) q2[++tt]=rt[i];
        int ll=1,rr=inf;
        while(ll!=rr) {
            int ans1=0,ans2=0;
            for(int i=h;i<=t;i++) 
                ans1+=val[ls[q1[i]]];
            for(int i=hh;i<=tt;i++)
                ans2+=val[ls[q2[i]]];
            int prt=t,prh=h;
            for(int i=prh;i<=prt;i++) {
                if(ans1-ans2>=k) {
                    if(ls[q1[i]]&&val[ls[q1[i]]]) q1[++t]=ls[q1[i]];
                }
                else 
                    if(rs[q1[i]]&&val[rs[q1[i]]]) q1[++t]=rs[q1[i]];
            }
            if(prt) h=prt+1;
            prt=tt; prh=hh;
            for(int i=prh;i<=prt;i++) {
                if(ans1-ans2>=k) {
                    if(ls[q2[i]]&&val[ls[q2[i]]]) q2[++tt]=ls[q2[i]];
                }
                else 
                    if(rs[q2[i]]&&val[rs[q2[i]]]) q2[++tt]=rs[q2[i]];
            }
            if(prt) hh=prt+1;
            if(ans1-ans2<k) {
                ll=(ll+rr)/2+1;
                k-=(ans1-ans2);
            }
            else rr=(ll+rr)/2;
        }
        return ll;
    }
    
    void pre(int x,int l,int r) {
        int rk=qry(l,r,1,x-1);
        if(rk<1) {
            printf("-2147483647
    ");
            return;
        }
        printf("%d
    ",kth(l,r,rk)-1);
    }
    
    void nxt(int x,int l,int r) {
        int rk=qry(l,r,1,x-1)+1;
        int fl=qry(l,r,x,x);
        if(fl) rk++;
        if(rk>r-l+1) {
            printf("2147483647
    ");
            return;
        }
        printf("%d
    ",kth(l,r,rk)-1);
    }
    
    int main() {
        srand(time(0));
        read(n); 
        read(T);
        for(register int i=1;i<=n;i++) {
            read(a[i]); a[i]++;
            change(i,a[i],1);
        }
        while(T--) {
            int o,l,r,k,pos,x;
            read(o);
            if(o==3) {
                read(pos); 
                read(x); x++;
                change(pos,x,0);
            }
            else {
                read(l); 
                read(r);
                read(k); if(o!=2) k++;
                if(o==1) printf("%d
    ",qry(l,r,1,k-1)+1);
                else if(o==2) printf("%d
    ",kth(l,r,k)-1);
                else if(o==4) pre(k,l,r);
                else if(o==5) nxt(k,l,r);
            }
        }
        return 0;
    }
    树状数组套权值线段树 洛谷二逼平衡树模板

    14.可持久化平衡树

    //Twenty
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<ctime>
    typedef long long LL;
    using namespace std;
    const int maxn=1e6+7;
    int n,tot,rt[maxn],ch[maxn*25][2],v[maxn*25],hr[maxn*25],sz[maxn*25];
    
    template<typename T> void read(T &x) {
        char ch=getchar(); T f=1; x=0;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    #define lc ch[x][0]
    #define rc ch[x][1] 
    void update(int x) {sz[x]=sz[lc]+sz[rc]+1;}
    
    void create(int &x,int y) {
        x=++tot;
        v[x]=y;
        lc=rc=0;
        sz[x]=1;
        hr[x]=rand();
    }
    
    void copy(int x,int y) {
        v[x]=v[y]; 
        lc=ch[y][0];
        rc=ch[y][1];
        sz[x]=sz[y];
        hr[x]=hr[y];
    }
    
    int merge(int x,int y) {
        if(!(x*y)) return x^y;
        int t=++tot;
        if(hr[x]<hr[y]) {
            copy(t,x);
            ch[t][1]=merge(ch[t][1],y);
        }
        else {
            copy(t,y);
            ch[t][0]=merge(x,ch[t][0]);
        }
        update(t);
        return t;
    }
    
    #define pr pair<int,int>
    #define se second
    #define fi first
    pr split(int x,int k) {
        if(!x) return make_pair(0,0);
        int t=++tot;
        copy(t,x);
        pr p;
        if(sz[lc]>=k) {
            p=split(ch[t][0],k);
            ch[t][0]=p.se; p.se=t;
        }
        else {
            p=split(ch[t][1],k-sz[lc]-1);
            ch[t][1]=p.fi; p.fi=t;
        }
        update(t);
        return p;
    }
    
    int rank(int root,int y) {
        int res=1;
        for(int x=root;x;) {
            if(v[x]<y) res+=(sz[lc]+1),x=rc;
            else x=lc;
        }
        return res;
    }
    
    int kth(int root,int k) {
        for(int x=root;x;) {
            if(sz[lc]+1==k) return v[x];
            if(sz[lc]+1<k) {k-=(sz[lc]+1); x=rc;}
            else x=lc;
        }
    }
    
    int exist(int root,int y) {
        int res=0;
        for(int x=root;x;) {
            if(v[x]==y) {res=1; break;}
            if(v[x]<y) x=rc;
            else x=lc;
        }
        return res;
    }
    
    void pre(int root,int y) {
        int res=-1;
        for(int x=root;x;) {
            if(v[x]<y) res=v[x],x=rc;
            else x=lc;
        }
        if(res==-1) printf("-2147483647
    ");
        else printf("%d
    ",res);
    }
    
    void nxt(int root,int y) {
        int res=-1;
        for(int x=root;x;) {
            if(v[x]>y) res=v[x],x=lc;
            else x=rc;
        }
        if(res==-1) printf("2147483647
    ");
        else printf("%d
    ",res);
    }
    
    void insert(int &x,int y) {
        int rk=rank(x,y)-1;
        pr p=split(x,rk);
        int z; create(z,y);
        x=merge(merge(p.fi,z),p.se);
    }
    
    void del(int &x,int y) {
        if(!exist(x,y)) return;
        int rk=rank(x,y)-1;
        pr p=split(x,rk);
        pr tp=split(p.se,1);
        x=merge(p.fi,tp.se);
    }
    
    int main() {
        srand(time(0));
        int lst,o,x;
        read(n);
        for(int i=1;i<=n;i++) {
            read(lst);
            read(o);
            read(x);
            rt[i]=rt[lst];
            switch(o) {
                case 1:insert(rt[i],x);break;
                case 2:del(rt[i],x);break;
                case 3:printf("%d
    ",rank(rt[i],x));break;
                case 4:printf("%d
    ",kth(rt[i],x));break;
                case 5:pre(rt[i],x);break;
                case 6:nxt(rt[i],x);break;
            }    
        }
        return 0;
    }
    可持久化非旋转treap

    ---------------------------------- 17-11-3------------------------------------

    终于把洛谷模板刷完啦!撒花~

  • 相关阅读:
    ubuntu apt 主要命令及参数
    加速度计
    window下Opengl与vs2012环境配置
    java文本输入输出小结
    markdown + 七牛云,让写文更容易
    SpringBoot系列:Spring Boot使用模板引擎Thymeleaf
    SpringBoot系列:Spring Boot集成Spring Cache,使用EhCache
    SpringBoot系列:Spring Boot集成Spring Cache
    SpringBoot系列:Spring Boot集成Spring Cache,使用RedisCache
    SpringBoot系列:Spring Boot使用模板引擎JSP
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7474919.html
Copyright © 2011-2022 走看看