splay 模板(4843: Lydsy3224 普通平衡树)
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数
下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=100000+10; int ch[maxn][2],size_[maxn],cnt[maxn],key[maxn],root,sz,f[maxn]; void clear(int x){ ch[x][1]=ch[x][0]=size_[x]=cnt[x]=key[x]=f[x]=0; } void update(int 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]]; } } bool get(int x){ return ch[f[x]][1]==x; } void Rotate(int x){ int old=f[x],oldf=f[old],which=get(x); ch[old][which]=ch[x][which^1]; f[ch[old][which]]=old; ch[x][which^1]=old; f[old]=x; f[x]=oldf; if(oldf){ ch[oldf][ch[oldf][1]==old]=x; } update(old); update(x); } void splay(int x){ for (int fa;(fa=f[x]);Rotate(x)){ if(f[fa]) { Rotate(get(x)==get(fa)?fa:x); } } root=x; } void myinsert(int x){ if(root==0){ sz++,key[sz]=x,root=sz,f[sz]=ch[sz][0]=ch[sz][1]=0,cnt[sz]=1,size_[sz]=1; return ; } int now=root,fa=0; while(1){ if(key[now]==x){ cnt[now]++; update(now); update(fa); splay(now); break; } fa=now; now=ch[now][key[now]<x]; if(now==0){ sz++; ch[sz][0]=ch[sz][1]=0; f[sz]=fa; size_[sz]=cnt[sz]=1; key[sz]=x; ch[fa][key[fa]<x]=sz; update(fa); splay(sz); break ; } } } int findx(int x){ int ans=0,now=root; while(1){ if(x<key[now]) now=ch[now][0]; else { ans+=(ch[now][0]?size_[ch[now][0]]:0); if(x==key[now]){ans+=1;splay(now);return ans;} ans+=cnt[now]; now=ch[now][1]; } } } int whox(int x){ int now=root; while(1){ if(ch[now][0]&&x<=size_[ch[now][0]]) now=ch[now][0]; else{ int temp=(ch[now][0]?size_[ch[now][0]]:0)+cnt[now]; if(x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } int pre(){ int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } int next(){ int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } void del(int x){ int pp=findx(x); if(cnt[root]>1) {cnt[root]--;update(root);return ;} if(!ch[root][0]&&!ch[root][1]){ clear(root); root=0; return ; } if(!ch[root][0]){ int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); return ; } else if(!ch[root][1]){ int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); return ; } int oldroot=root,qian=pre(); splay(qian); ch[root][1]=ch[oldroot][1]; f[ch[oldroot][1]]=root; clear(oldroot); update(root); } int main(){ int n; scanf("%d",&n); int op,x; while(n--){ scanf("%d%d",&op,&x); if(op==1) myinsert(x); if(op==2) del(x); if(op==3) printf("%d\n",findx(x)); if(op==4) printf("%d\n",whox(x)); if(op==5) { myinsert(x); printf("%d\n",key[pre()]); del(x); } if(op==6){ myinsert(x); printf("%d\n",key[next()]); del(x); } } return 0; }