[模板]Splay

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 x 数
  2. 删除 x 数(若有多个相同的数,因只删除一个)
  3. 查询 x 数的排名(排名定义为比当前数小的数的个数 +1 。若有多个相同的数,因输出最小的排名)
  4. 查询排名为 x 的数
  5. 求 x 的前驱(前驱定义为小于 x ,且最大的数)
  6. 求 x 的后继(后继定义为大于 x ,且最小的数)

输入输出格式

输入格式

  第一行为 n ,表示操作的个数,下面 n 行每行有两个数 opt 和 xx ,opt 表示操作的序号

输出格式

  对于操作 3,4,5,6 每行输出一个数,表示对应答案

  1 #include<cstdio>
  2 #define root e[0].ch[1]
  3 using namespace std;
  4 const int maxn=1e5+5;
  5 int siz;
  6 struct cp{
  7     int fa,ch[2],num,v,siz;
  8 }e[maxn];
  9 inline void clear(int x){e[x]=(cp){0,0,0,0,0,0};}
 10 inline bool get(int x){return e[e[x].fa].ch[1]==x;}
 11 inline void con(int x,int fa,int f){e[e[x].fa=fa].ch[f]=x;}
 12 inline void update(int x){
 13     if(!x) return ;
 14     e[x].siz=e[x].num;
 15     if(e[x].ch[0]) e[x].siz+=e[e[x].ch[0]].siz;
 16     if(e[x].ch[1]) e[x].siz+=e[e[x].ch[1]].siz;
 17 }
 18 inline void rotate(int x){
 19     if(!e[x].fa) return ;
 20     int fa=e[x].fa,ffa=e[e[x].fa].fa;
 21     bool f1=get(x),f2=get(fa);
 22     con(e[x].ch[!f1],fa,f1),con(fa,x,!f1),con(x,ffa,f2);
 23     update(fa),update(x);
 24 }
 25 inline void splay(int x){
 26     for(int fa;fa=e[x].fa;rotate(x))
 27         if(e[fa].fa) rotate(get(x)==get(fa)?fa:x);
 28 }
 29 inline int findx(int v){
 30     int now=root;
 31     while(e[now].v!=v) now=e[now].ch[e[now].v<v];
 32     return now;
 33 }
 34 inline int find(int v){
 35     int now=root,s=1;
 36     while(e[now].v!=v){
 37         if(e[now].v<v) s+=e[e[now].ch[0]].siz+e[now].num;
 38         now=e[now].ch[e[now].v<v];
 39     }
 40     return s+e[e[now].ch[0]].siz;
 41 }
 42 inline int rank(int x){
 43     int now=root;
 44     while(1)
 45         if(e[e[now].ch[0]].siz>=x) now=e[now].ch[0];
 46         else{
 47             x-=e[e[now].ch[0]].siz;
 48             if(x<=e[now].num) return e[now].v;
 49             x-=e[now].num,now=e[now].ch[1];
 50         }
 51 }
 52 inline int pre(bool f){
 53     int now=e[root].ch[f];
 54     while(e[now].ch[!f]) now=e[now].ch[!f];
 55     return now;
 56 }
 57 inline void insert(int v){
 58     if(!root){
 59         e[++siz].v=v,con(siz,0,1),e[siz].siz=e[siz].num=1;
 60         return ;
 61     }
 62     int now=root,fa=0;
 63     while(1){
 64         if(e[now].v==v){
 65             ++e[now].num,++e[now].siz;
 66             if(fa) ++e[fa].siz;
 67             splay(now);
 68             return ;
 69         }
 70         now=e[fa=now].ch[e[now].v<v];
 71         if(!now){
 72             e[++siz].v=v,e[siz].num=e[siz].siz=1;
 73             con(siz,fa,e[fa].v<v),e[fa].siz++,splay(siz);
 74             return ;
 75         }
 76     }
 77 }
 78 inline void del(int v){
 79     int x=findx(v);
 80     splay(x);
 81     if(e[x].num>1) e[x].num--,e[x].siz--;
 82     else if(!e[x].ch[1]&&!e[x].ch[0]) clear(x),root=0;
 83     else if(!e[x].ch[1]||!e[x].ch[0])
 84         con(e[x].ch[!e[x].ch[0]],0,1),clear(x);
 85     else splay(pre(0)),con(e[x].ch[1],root,1),clear(x),e[root].siz--;
 86 }
 87 inline int read(){
 88     char ch=getchar();
 89     int x=0,f=1;
 90     while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
 91     while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
 92     return x*f;
 93 }
 94 int main(){
 95     int n=read(),f,x;
 96     while(n--){
 97         f=read(),x=read();
 98         if(f==1) insert(x);
 99         else if(f==2) del(x);
100         else if(f==3) printf("%d\n",find(x));
101         else if(f==4) printf("%d\n",rank(x));
102         else{
103             insert(x);
104             printf("%d\n",e[pre(f-5)].v);
105             del(x);
106         }
107     }
108     return 0;
109 }
Splay

 

posted @ 2018-06-02 20:09  Rising_Date  阅读(164)  评论(0编辑  收藏  举报