平衡树

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
map<int,int> bh;
int key[100010];
int fa[100010];
int ch[100010][2];
int sz[100010];
int cnt[100010];
int t1,t2,tot,root;
int inf=2147483646;
bool dir(int x){return x==ch[fa[x]][1];}
void find_pre(int i,int x){
    if(key[i]==0)
        return ;
    if(key[i]<x){
        t1=key[i];
        find_pre(ch[i][1],x);
    }
    else
        find_pre(ch[i][0],x);
}
void find_nxt(int i,int x){
    if(key[i]==0)
        return ;
    if(key[i]>x){
        t2=key[i];
        find_nxt(ch[i][0],x);
    }
    else
        find_nxt(ch[i][1],x);
}
void up(int x){
    sz[0]=0;
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}
void rotate(int x){
    bool b=dir(x);int y=fa[x];
    int z=fa[y];int a=ch[x][!b];
    if(z==0)
        root=x;
    else
        ch[z][dir(y)]=x;
    fa[x]=z;fa[y]=x;
    ch[x][!b]=y;ch[y][b]=a;
    if(a!=0)
        fa[a]=y;
    up(y);up(x);
    if(z!=0)up(z);
}
void splay(int x,int i){
    bool b,c;
    while(fa[x]!=i){
        int y=fa[x];int z=fa[y];
        if(z==i)    rotate(x);
        else{
            b=dir(x),c=dir(y);
            if(b^c) {   rotate(x);rotate(x);}
            else    {   rotate(y);rotate(x);}
        }
    }
    if(i==0)    root=x;
}
void insert(int k,int x,int last){
    if(x==key[k]){
        cnt[k]++;
        up(k);  up(fa[k]);
        return ;
    }
    if(!k){
        k=++tot;
        bh[x]=k;
        key[k]=x;
        cnt[k]=1;
        sz[k]=1;
        fa[k]=last;
        if(key[k]<key[last])    ch[last][0]=k;
        else ch[last][1]=k;
        splay(k,0);
        return ;
    }
    if(x<key[k]){
        insert(ch[k][0],x,k);
        up(k);
        return ;
    }
    else{
        insert(ch[k][1],x,k);
        up(k);
        return ;
    }
}

void del(int y){
    int x=bh[y];
    splay(x,0);
    cnt[x]--;sz[x]--;
    if(cnt[x]==0){
        sz[0]=0;
        if(sz[ch[x][0]]==0){
            root=ch[x][1];
            fa[ch[x][1]]=0;
        }
        else if(sz[ch[x][1]]==0){
            root=ch[x][0];
            fa[ch[x][0]]=0;
        }
        else{
            t1=-inf;
            find_pre(root,y);
            int h=bh[t1];
            splay(h,x);
            root=h;
            fa[h]=0;
            ch[h][1]=ch[x][1];
            fa[ch[x][1]]=h;
            up(root);
        }
        key[x]=0;
        fa[x]=0;
        ch[x][0]=0;
        ch[x][1]=0;
    }
}
int rank_to_num(int dq,int rank){
    sz[0]=0;
    if(sz[ch[dq][0]]>=rank)
        return rank_to_num(ch[dq][0],rank);
    if(sz[ch[dq][0]]+cnt[dq]<rank)
        return rank_to_num(ch[dq][1],rank-sz[ch[dq][0]]-cnt[dq]);
    return key[dq];
}
int main()
{
    int n,x,y;scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x,&y);
        if(x==1){
            insert(root,y,0);
            up(root);
        }
        if(x==2)
            del(y);
        if(x==3){
            sz[0]=0;
            splay(bh[y],0);
            printf("%d\n",sz[ch[root][0]]+1);
        }
        if(x==4)
            printf("%d\n",rank_to_num(root,y));
        if(x==5){
            t1=y;
            find_pre(root,y);
            printf("%d\n",t1);
        }
        if(x==6){
            t2=inf;
            find_nxt(root,y);
            printf("%d\n",t2);
        }   
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值