平衡树-Splay

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define inf (int)(1e9+1000)
#define maxn (int)(1e5+1000)
using namespace std;
int fa[maxn],size[maxn],cnt[maxn],son[maxn][2],val[maxn];
int n,root,beh,fro,idx;
void maintain(int x){
    size[x]=cnt[x];
    if(son[x][0])size[x]+=size[son[x][0]];
    if(son[x][1])size[x]+=size[son[x][1]];
    return;
}
void clear(int x){
    int y=fa[x];fa[x]=0;
    if(!x)return;//test
    if(son[y][0]==x)son[y][0]=0;
    else son[y][1]=0;
    return;
}
void rotate(int x){
    int y=fa[x],z=fa[y],o=(son[y][1]==x);

    son[y][o]=son[x][o^1];
    fa[son[x][o^1]]=y;

    son[x][o^1]=y;
    fa[y]=x;

    son[z][son[z][1]==y]=x;
    fa[x]=z;

    maintain(y);
    maintain(x);
}
void splay(int x){
    for(int y;(y=fa[x]);rotate(x)){
        if(!fa[y])continue;
        rotate(((son[fa[y]][0]==y)==(son[fa[x]][0]==x))?y:x);
    }
    root=x;
}
void insert(int x,int a){
    int y=0;
    while(x&&val[x]!=a){
        y=x;
        x=son[x][a>val[x]];
    }
    if(x){
        size[x]++;cnt[x]++;
    }
    else{
        x=++idx;
        cnt[x]=1;
        fa[x]=y;
        son[y][a>val[y]]=x;
        size[x]=1;
        val[x]=a;
    }
    splay(x);
}
void del(int x){
    splay(x);
    if(cnt[x]>1){cnt[x]--;maintain(x);splay(x);return;}
    root=son[x][1];int move=son[x][0];
    clear(son[x][0]);clear(son[x][1]);
    int y=0,now=root;
    while(now){
        y=now;size[y]+=size[move];
        now=son[now][0];
    }
    fa[move]=y;son[y][0]=move;
    splay(move);
    return;
}
void pre(int x,int a){
    if(!x)return;
    while(x){
        if(val[x]<a){
            fro=x;
            x=son[x][1];
        }else{
            x=son[x][0];
        }
    }
    return;
}
void suc(int x,int a){
    if(!x)return;
    while(x){
        if(val[x]>a){
            beh=x;
            x=son[x][0];
        }
        else{
            x=son[x][1];
        }
    }
    return;
}
int kth(int x,int a){
    while(1){
        if(a<=size[son[x][0]]){//test
            x=son[x][0];
        }
        else{
            a-=size[son[x][0]]+cnt[x];
            if(a<=0)return x;
            x=son[x][1];
        }
    }
    return 0;
}
int rk(int x,int a){
    int rank=0;
    while(1){
        if(a<val[x]){
            x=son[x][0];
        }
        else{
            rank+=size[son[x][0]];
            if(a==val[x]){
                splay(x);
                return rank+1;
            }
            rank+=cnt[x];
            x=son[x][1];
        }
    }
    return rank;
}
int get(int a){
    int x=root;
    while(1){
        if(val[x]==a)return x;
        x=son[x][a>val[x]];
    }
    return 0;
}
int main(){
    scanf("%d",&n);
    insert(root,inf);insert(root,-inf);
    for(int i=1;i<=n;i++){
        int opt,x;scanf("%d%d",&opt,&x);
        if(opt==1)insert(root,x);
        else if(opt==2)del(get(x));
        else if(opt==3)printf("%d\n",rk(root,x)-1);
        else if(opt==4)printf("%d\n",val[kth(root,x+1)]);
        else if(opt==5){pre(root,x);printf("%d\n",val[fro]);}
        else if(opt==6){suc(root,x);printf("%d\n",val[beh]);}
    }
}
posted @ 2019-04-23 20:10  GavinZheng  阅读(225)  评论(0编辑  收藏  举报