splay

来源:互联网 发布:mac机械硬盘开机速度 编辑:程序博客网 时间:2024/03/29 02:10

背不过,抄了个板子

#include<cstdio>#define ll long longusing 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);        }    }}