高级数据结构模板

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------------------------------------

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

原文地址:https://www.cnblogs.com/Achenchen/p/7474919.html