Splay板子

本代码由张大仙独家冠名
从张大仙那里翻译而来。原链接大仙的Splay超详细讲解!学Splay这一篇就够了!
代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10,Inf=0x3f3f3f3f;
int ch[maxn][2],cnt[maxn],size[maxn],val[maxn],fa[maxn];
int root,tot,n,m;
void update(int x){
    size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
void rotate(int x){
    int y=fa[x],z=fa[y],k=(ch[y][1]==x) ;
    ch[z][ch[z][1]==y] = x;
    fa[x]=z;
    ch[y][k]=ch[x][!k];
    fa[ch[x][!k]]=y;
    ch[x][!k]=y;
    fa[y]=x;
    update(y);
    update(x);
}
void Splay(int x,int t){
    while(fa[x]!=t){
        int y=fa[x],z=fa[y];
        if(z!=t) (ch[y][0]==x)^(ch[z][0]==y) ? rotate(y) : rotate(x) ;
        rotate(x);
    }
    if(!t) root=x;
}
void find(int x){
    int u=root;
    while(ch[u][x>val[u]]&&x!=val[u]) u=ch[u][x>val[u]];
    Splay(u,0);
}
void Insert(int x){
    int u=root,f=0;
    while(u && x!=val[u]){
        f=u;
        u=ch[u][x>val[u]];
    }
    if(u) cnt[u]++;
    else{
        u=++tot;
        if(f) ch[f][x>val[f]] = u;
        val[u]=x;
        fa[u]=f;
        cnt[u]=size[u]=1;
    }
    Splay(u,0);
}
int pre(int x){
    find(x);
    if(x>val[root]) return root;
    int u=ch[root][0];
    if(!u) return -1;
    while(ch[u][1]) u=ch[u][1];
    return u;
}
int next(int x){
    find(x);
    if(x<val[root]) return root;
    int u=ch[root][1];
    if(!u) return -1;
    while(ch[u][0]) u=ch[u][0];
    return u;
}
void Delete(int x){
    int xp=pre(x),xn=next(x);
    Splay(xp,0);
    Splay(xn,root);
    int u=ch[xn][0];
    if(cnt[u]>1){
        cnt[u]--;
        Splay(u,0);
    }
    else{
        ch[xn][0]=0;
        update(xp);
        update(xn);
    }
}
int kth(int x){
    int u=root;
    if(size[u]<x) return -1;
    while(1){
        if(x<=size[ch[u][0]]) u=ch[u][0];
        else if(x>size[ch[u][0]]+cnt[u]){
            x-=size[ch[u][0]]+cnt[u];
            u=ch[u][1];
        }
        else return u;
    }
}
int rank(int x){
    find(x);
    return size[ch[root][0]];
}
void Solve(){
    scanf("%d",&n);
    Insert(-Inf);Insert(Inf);
    for(int i=1,op,x;i<=n;++i){
        scanf("%d%d",&op,&x);
        if(op==1) Insert(x);
        else if(op==2) Delete(x);
        else if(op==3) printf("%d\n",rank(x)); 
        else if(op==4) printf("%d\n",val[kth(x+1)]);
        else if(op==5) printf("%d\n",val[pre(x)]);
        else printf("%d\n",val[next(x)]);
    }
}
int main(){
    Solve();
    return 0;
}
posted @ 2020-08-13 14:37  “起个名字真难♘”  阅读(165)  评论(0编辑  收藏  举报