题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个)
-
查询x数的排名(若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
-
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例#1:
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
输出样例#1:
106465 84185 492737
说明
时空限制:1000ms,128M
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
代码
#include<cstdio> #define N 100010 using namespace std; int fa[N],ch[N][2],siz[N],cnt[N],date[N],root,nn,n,tot; int son(int x) { return x==ch[fa[x]][1]; } void pushup(int rt) { int l=ch[rt][0],r=ch[rt][1]; siz[rt]=siz[l]+siz[r]+cnt[rt]; } void rotate(int x) { int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b]; if(z)ch[z][c]=x;else root=x;fa[x]=z; if(a)fa[a]=y;ch[y][b]=a; ch[x][!b]=y;fa[y]=x;/// pushup(y);pushup(x); } void splay(int x,int i) { while(fa[x]!=i) { int y=fa[x],z=fa[y]; if(z==i) { rotate(x); } else { if(son(x)==son(y)) { rotate(y);rotate(x); } else { rotate(x);rotate(x); } } } } void ins(int &rt,int x) { if(rt==0) { rt=++nn; date[nn]=x; siz[nn]=cnt[nn]=1; return; } if(x==date[rt]) { cnt[rt]++;siz[rt]++; return; } if(x<date[rt]) { ins(ch[rt][0],x); fa[ch[rt][0]]=rt; pushup(rt); } else { ins(ch[rt][1],x); fa[ch[rt][1]]=rt; pushup(rt); } } int getpre(int rt,int x) { int p=rt,ans; while(p) { if(x<=date[p]) { p=ch[p][0];/// } else { ans=p; p=ch[p][1]; } } return ans; } int getsuc(int rt,int x) { int p=rt,ans; while(p) { if(x>=date[p]) { p=ch[p][1]; } else { ans=p; p=ch[p][0]; } } return ans; } int getmn(int rt) { int p=rt,ans=-1; while(p) { ans=p; p=ch[p][0]; } return ans; } void del(int rt,int x) { if(date[rt]==x) { if(cnt[rt]>1) { cnt[rt]--;siz[rt]--; } else { splay(rt,0); int p=getmn(ch[rt][1]); if(p!=-1) { splay(p,rt); root=p;fa[p]=0; ch[p][0]=ch[rt][0];fa[ch[rt][0]]=p; pushup(p); } else { root=ch[rt][0];fa[ch[rt][0]]=0; } } return; } if(x<date[rt]) { del(ch[rt][0],x); pushup(rt);/// } else { del(ch[rt][1],x); pushup(rt); } } int getk(int rt,int k) { if(date[rt]==k) { splay(rt,0); if(ch[rt][0]==0) { return 1; } else { return siz[ch[rt][0]]+1; } } if(k<date[rt]) return getk(ch[rt][0],k); else return getk(ch[rt][1],k); } int getkth(int rt,int k) { int l=ch[rt][0]; if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return date[rt]; if(k<siz[l]+1) return getkth(ch[rt][0],k); if(siz[l]+cnt[rt]<k) return getkth(ch[rt][1],k-(siz[l]+cnt[rt])); } int main() { scanf("%d",&n); while(n--) { int opt,x; scanf("%d%d",&opt,&x); if(opt==1) { tot++; ins(root,x); } if(opt==2) { tot--; del(root,x); } if(opt==3) { printf("%d ",getk(root,x)); } if(opt==4) { printf("%d ",getkth(root,x)); } if(opt==5) { printf("%d ",date[getpre(root,x)]); } if(opt==6) { printf("%d ",date[getsuc(root,x)]); } } return 0; }