BZOJ3224:普通平衡树(splay练习)
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598Sample Output106465 84185 492737 Hint
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
不多说了,模板练习。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int maxn=100010; struct Splay{ int ch[maxn][2],fa[maxn],num[maxn],sz[maxn],key[maxn],rt,cnt; int get(int x) { return ch[fa[x]][1]==x;} Splay(){ rt=cnt=0; } void update(int Now) { if(!Now) return ; sz[Now]=num[Now]; if(ch[Now][0]) sz[Now]+=sz[ch[Now][0]]; if(ch[Now][1]) sz[Now]+=sz[ch[Now][1]]; } void rotate(int x) { int old=fa[x],fold=fa[old],opt=(ch[old][1]==x); fa[ch[x][opt^1]]=old; ch[old][opt]=ch[x][opt^1]; ch[x][opt^1]=old; fa[old]=x; fa[x]=fold; if(fold) ch[fold][ch[fold][1]==old]=x; else rt=x; update(old); update(x); } void splay(int x,int y) { for(int f;(f=fa[x])!=y;rotate(x)){ if(fa[f]!=y) rotate(get(x)==get(f)?f:x); } if(!y) rt=x; } void insert(int x) { if(!rt){ rt=++cnt; key[cnt]=x; sz[cnt]=num[cnt]=1; return ; } int Now=rt,f=0; while(true){ if(key[Now]==x){ num[Now]++; update(Now); update(f); splay(Now,0); return; } f=Now; Now=ch[Now][key[Now]<x]; if(!Now) { fa[++cnt]=f; ch[f][key[f]<x]=cnt; num[cnt]=sz[cnt]=1; key[cnt]=x; update(f); splay(cnt,0); return ; } } } void del(int x) { int whatever=find(x); if(num[rt]>1){num[rt]--; update(rt); return;} if(!ch[rt][0]&&!ch[rt][1]) { rt=0; return;} if(!ch[rt][0]){ int oldroot=rt; rt=ch[rt][1]; fa[rt]=0; return; } else if (!ch[rt][1]){ int oldroot=rt; rt=ch[rt][0]; fa[rt]=0; return; } int leftbig=pre(),oldroot=rt; splay(leftbig,0); ch[rt][1]=ch[oldroot][1]; fa[ch[oldroot][1]]=rt; update(rt); } int find(int x) { int Now=rt,res=0; while(true){ if(x<key[Now]) Now=ch[Now][0]; else { res+=ch[Now][0]?sz[ch[Now][0]]:0; if(key[Now]==x) { splay(Now,0);return res+1; } res+=num[Now]; Now=ch[Now][1]; } } } int findx(int x) { int Now=rt; while(true){ if(ch[Now][0]&&sz[ch[Now][0]]>=x) Now=ch[Now][0]; else { if(ch[Now][0]) x-=sz[ch[Now][0]]; if(num[Now]>=x) return key[Now]; x-=num[Now]; Now=ch[Now][1]; } } } int pre() { int Now=ch[rt][0]; while(ch[Now][1]) Now=ch[Now][1]; return Now; } int nxt() { int Now=ch[rt][1]; while(ch[Now][0]) Now=ch[Now][0]; return Now; } }S; int main() { int N,opt,x; scanf("%d",&N); while(N--){ scanf("%d%d",&opt,&x); switch(opt){ case 1: S.insert(x); break; case 2: S.del(x); break; case 3: printf("%d\n",S.find(x)); break; case 4: printf("%d\n",S.findx(x)); break; case 5: S.insert(x); printf("%d\n",S.key[S.pre()]); S.del(x);break; case 6: S.insert(x); printf("%d\n",S.key[S.nxt()]); S.del(x);break; } } return 0; }
It is your time to fight!