[模板]Splay
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x 数
- 删除 x 数(若有多个相同的数,因只删除一个)
- 查询 x 数的排名(排名定义为比当前数小的数的个数 +1 。若有多个相同的数,因输出最小的排名)
- 查询排名为 x 的数
- 求 x 的前驱(前驱定义为小于 x ,且最大的数)
- 求 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 }
来自一只刚参加过NOIP的蒟蒻