Description
这是一道模板题。
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x 数;
- 删除 x数(若有多个相同的数,因只删除一个);
- 查询 x 数的排名(若有多个相同的数,因输出最小的排名);
- 查询排名为 x 的数;
- 求 x 的前趋(前趋定义为小于 x ,且最大的数);
- 求 x 的后继(后继定义为大于 x,且最小的数)。
Input
第一行为 n ,表示操作的个数,下面 n 行每行有两个数 opt 和 x,opt 表示操作的序号(1≤opt≤6)。
Output
对于操作 3、4、5、6 每行输出一个数,表示对应答案。
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
HINT
1≤n≤105,−107≤x≤107
思路:Treap模板
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 100007; int i,j,k,l,ans,num,root,x,op,n; int size[maxn],key[maxn],sum[maxn],sam[maxn]; int t[maxn][2]; void update(int x) { size[x]=size[t[x][0]]+size[t[x][1]]+sam[x]; } void rotate(int &x,int z) { int y=t[x][z]; t[x][z]=t[y][1-z]; t[y][1-z]=x; update(x);update(y); x=y; } void insert(int &x,int y) { if(!x) { x=++num;size[x]=1;sam[x]=1;key[x]=rand();sum[x]=y; return ; } size[x]++; if(sum[x]==y) sam[x]++; else if(y>sum[x]) { insert(t[x][1],y); if(key[t[x][1]]<key[x]) rotate(x,1); } else { insert(t[x][0],y); if(key[t[x][0]]>key[x]) rotate(x,0); } } void del(int &x,int y) { if(!x) return ; if(sum[x]==y) { if(sam[x]>1) { size[x]--,sam[x]--;return ; } else if(t[x][0]*t[x][1]==0) x=t[x][0]+t[x][1]; else { if(key[t[x][0]]<key[t[x][1]]) rotate(x,0),del(x,y); else rotate(x,1),del(x,y); } } else if(y>sum[x]) size[x]--,del(t[x][1],y); else size[x]--,del(t[x][0],y); } int posnum(int x,int y) { if(!x) return 0; if(sum[x]==y) return size[t[x][0]]+1; else if(sum[x]<y) return posnum(t[x][1],y)+sam[x]+size[t[x][1]]; else return posnum(t[x][0],y); } int posrank(int x,int y) { if(!x) return 0; if(size[t[x][0]]>=y) return posrank(t[x][0],y); else if(size[t[x][0]]+sam[x]<y) return posrank(t[x][1],y-size[t[x][0]]-sam[x]); else return sum[x]; } void pospre(int x,int y) { if(!x) return ; if(sum[x]<y) ans=sum[x],pospre(t[x][1],y); else pospre(t[x][0],y); } void possub(int x,int y) { if(!x) return ; if(sum[x]>y) ans=sum[x],possub(t[x][0],y); else possub(t[x][1],y); } int main(void) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&op,&x); switch(op) { case 1:insert(root,x);break; case 2:del(root,x);break; case 3:printf("%d ",posnum(root,x));break; case 4:printf("%d ",posrank(root,x));break; case 5:ans=0;pospre(root,x);printf("%d ",ans);break; case 6:ans=0;possub(root,x);printf("%d ",ans);break; } } return 0; }
参考文章:https://blog.csdn.net/doyouseeman/article/details/52049675