luogu3369 普通平衡树

传送门

平衡树模板。插入两个哨兵节点防止出错,好像是把数删完的时候,0结点的父亲会出问题导致死循环。总之加两个保险。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int oo=1<<30;
int n,x,op;
int root=0,tot=0,fa[maxn],cnt[maxn],son[maxn][2],size[maxn],val[maxn];
inline int get(int x){return x==son[fa[x]][1];}
inline void pushup(int x){size[x]=size[son[x][1]]+size[son[x][0]]+cnt[x];}
inline void rotate(int x){
    int y=fa[x],z=fa[y],k=get(x),l=son[x][k^1];
    son[y][k]=l,fa[l]=y;
    son[z][get(y)]=x,fa[x]=z;
    son[x][k^1]=y,fa[y]=x;
    pushup(y),pushup(x);
}
inline void splay(int x,int goal=0){
    while(fa[x]!=goal){
        int y=fa[x],z=fa[y];
        if(z!=goal) rotate((get(x)==get(y))?(y):(x));
        rotate(x);
    }if(!goal) root=x;
}
inline void insert(int x){
    int now=root,f=0;
    while(now&&x!=val[now]) f=now,now=son[now][val[now]<x];
    if(now) cnt[now]++;
    else{
        now=++tot;
        if(f) son[f][val[f]<x]=now;
        val[now]=x,fa[now]=f,cnt[now]=size[now]=1,son[now][0]=son[now][1]=0;
    }
    splay(now);
}
inline void find(int x){
    int now=root;
    while(son[now][val[now]<x]&&x!=val[now])
        now=son[now][val[now]<x];
    splay(now);
}
inline int kth(int k){
    int now=root;
    while(1){
        if(k<=size[son[now][0]]) now=son[now][0];
        else if(k<=size[son[now][0]]+cnt[now]) return now;
        else k-=size[son[now][0]]+cnt[now],now=son[now][1];
    }return now;
}
inline int prefix(int x){
    find(x);
    if(val[root]<x) return root;
    int now=son[root][0];
    while(son[now][1]) now=son[now][1];
    return now;
}
inline int suffix(int x){
    find(x);
    if(val[root]>x) return root;
    int now=son[root][1];
    while(son[now][0]) now=son[now][0];
    return now;
}
inline void del(int x){
    int lst=prefix(x),nxt=suffix(x);
    splay(lst),splay(nxt,lst);
    int D=son[nxt][0];
    if(cnt[D]>1) cnt[D]--,splay(D);
    else son[nxt][0]=0;
}
inline int read(){
    int f=1,x=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void print(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int main(){
    n=read(),insert(oo),insert(-oo);
    for(int i=1;i<=n;++i){
        op=read(),x=read();
        if(op==1) insert(x);
        if(op==2) del(x);
        if(op==3) find(x),print(size[son[root][0]]),putchar(10);
        if(op==4) print(val[kth(x+1)]),putchar(10);
        if(op==5) print(val[prefix(x)]),putchar(10);
        if(op==6) print(val[suffix(x)]),putchar(10);
    }
}

猜你喜欢

转载自blog.csdn.net/g21wcr/article/details/88777176
今日推荐