splay

背不过,抄了个板子

#include<cstdio>
#define ll long long
using namespace std;

ll n,root,sz;
struct tree{
    ll ch[110000][3];
    ll key[110000],size[190099],cnt[110000],f[110000];
    inline void clear(ll x){  
         ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=size[x]=0;  
    }  
    inline ll get(ll x){  
         return ch[f[x]][1]==x;  
    }  
    inline void update(ll x){  
         if (x){  
              size[x]=cnt[x];  
              if (ch[x][0]) size[x]+=size[ch[x][0]];  
              if (ch[x][1]) size[x]+=size[ch[x][1]];  
         }  
    }  
    inline void rotate(ll x){  
         ll old=f[x],oldf=f[old],which=get(x);  
         ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;  
         f[old]=x;ch[x][which^1]=old;  
         f[x]=oldf;  
         if (oldf)  
              ch[oldf][ch[oldf][1]==old]=x;  
         update(old);update(x);  
    }  
    inline void splay(ll x){  
         for (ll fa;(fa=f[x]);rotate(x))  
              if (f[fa])  
                   rotate((get(x)==get(fa)?fa:x));  
         root=x;  
    }   
    inline void insert(ll v){  
         if (root==0) {sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;key[sz]=v;cnt[sz]=1;size[sz]=1;root=sz;return;}  
         ll now=root,fa=0;  
         while (1){  
              if (key[now]==v){  
                   cnt[now]++;update(now);update(fa);splay(now);break;  
              }  
              fa=now;  
              now=ch[now][key[now]<v];  
              if (now==0){  
                   sz++;  
                   ch[sz][0]=ch[sz][1]=0;key[sz]=v;size[sz]=1;  
                   cnt[sz]=1;f[sz]=fa;ch[fa][key[fa]<v]=sz;  
                   update(fa);  
                   splay(sz);  
                   break;  
              }  
         }  
    }  
    inline ll find(ll v){  
         ll ans=0,now=root;  
         while (1){  
              if (v<key[now])  
                   now=ch[now][0];  
              else{  
                   ans+=(ch[now][0]?size[ch[now][0]]:0);  
                   if (v==key[now]) {splay(now);return ans+1;}  
                   ans+=cnt[now];  
                   now=ch[now][1];  
              }  
         }  
    }  
    inline ll findx(ll x){  
         ll now=root;  
         while (1){  
              if (ch[now][0]&&x<=size[ch[now][0]])  
                   now=ch[now][0];  
              else{  
                   ll temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];  
                   if (x<=temp)  
                        return key[now];  
                   x-=temp;now=ch[now][1];  
              }  
         }  
    }  
    inline ll pre(){  
         ll now=ch[root][0];  
         while (ch[now][1]) now=ch[now][1];  
         return now;  
    }  

    inline ll next(){  
         ll now=ch[root][1];  
         while (ch[now][0]) now=ch[now][0];  
         return now;  
    }  
    inline void del(ll x){  
         ll whatever=find(x);  
         if (cnt[root]>1) {cnt[root]--;return;}  
         //Only One Point  
         if (!ch[root][0]&&!ch[root][1]) {clear(root);root=0;return;}  
         //Only One Child  
         if (!ch[root][0]){  
              ll oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;  
         }  
         else if (!ch[root][1]){  
              ll oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;  
         }  
         //Two Children  
         ll leftbig=pre(),oldroot=root;  
         splay(leftbig);  
         f[ch[oldroot][1]]=root;  
         ch[root][1]=ch[oldroot][1];  
         clear(oldroot);  
         update(root);  
         return;  
    }  
}s; 
int main(){
    scanf("%lld",&n);
    while(n--){
        ll opt,x;
        scanf("%lld%lld",&opt,&x);
        if(opt==1) s.insert(x);
        if(opt==2) s.del(x);
        if(opt==3) printf("%lld\n",s.find(x));
        if(opt==4) printf("%lld\n",s.findx(x));
        if(opt==5) {
            s.insert(x);
            s.find(x);
            printf("%lld\n",s.key[s.pre()]);
            s.del(x);
        }
        if(opt==6){
            s.insert(x);
            s.find(x);
            printf("%lld\n",s.key[s.next()]);
            s.del(x);
        }
    }
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值