题目:
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
题解:
splay模板题···表示两周没碰键盘手都生了····
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=100005; int root,size[N],son[N][2],key[N],cnt[N],tot,father[N]; int a,b,n; inline void clear(int now) { size[now]=son[now][0]=son[now][1]=key[now]=cnt[now]=father[now]=0; } inline void update(int now) { if(now) { size[now]=cnt[now]; if(son[now][0]) size[now]+=size[son[now][0]]; if(son[now][1]) size[now]+=size[son[now][1]]; } } inline int get(int a) { return son[father[a]][1]==a; } inline void rotate(int now) { int fa=father[now],ofa=father[fa],which=get(now); son[fa][which]=son[now][which^1],father[son[fa][which]]=fa; son[now][which^1]=fa,father[fa]=now,father[now]=ofa; if(ofa) son[ofa][son[ofa][1]==fa]=now; update(fa),update(now); } inline void splay(int now) { while(father[now]) { if(father[father[now]]) rotate(get(now)==get(father[now])?father[now]:now); rotate(now); } root=now; } inline void insert(int x) { int now=root,last=0; while(true) { if(!now) { now=++tot;size[now]=cnt[now]=1;father[now]=last;key[now]=x; son[last][key[now]>key[last]]=now;update(last);splay(now); break; } if(key[now]==x) { cnt[now]++;update(now);update(last);splay(now); break; } last=now;now=son[now][x>key[now]]; } } inline int find(int x) { int now=root,ans=0; while(true) { if(x<key[now]) now=son[now][0]; else { ans+=size[son[now][0]]; if(x==key[now]) {splay(now);return ans+1;} ans+=cnt[now];now=son[now][1]; } } } inline int findx(int x) { int now=root; while(true) { if(x<=size[son[now][0]]) now=son[now][0]; else { int temp=size[son[now][0]]+cnt[now]; if(x<=temp) return key[now]; x-=temp;now=son[now][1]; } } } inline int pre() { int now=son[root][0]; while(son[now][1]) now=son[now][1]; return now; } inline int next() { int now=son[root][1]; while(son[now][0]) now=son[now][0]; return now; } inline void Delete(int x) { int nothing=find(x); if(cnt[root]>1) {cnt[root]--;return;} else if(!son[root][0]&&!son[root][1]) {clear(root);root=0;return;} else if(!son[root][0]) {int oldroot=root;root=son[root][1];father[root]=0;clear(oldroot);return;} else if(!son[root][1]) {int oldroot=root;root=son[root][0];father[root]=0;clear(oldroot);return;} else { int leftbig=pre(),oldroot=root; splay(leftbig);son[root][1]=son[oldroot][1]; father[son[root][1]]=root;clear(oldroot); update(root); return; } } inline int findpre(int x) { insert(x);int temp=pre(); Delete(x);return key[temp]; } inline int findnext(int x) { insert(x);int temp=next(); Delete(x);return key[temp]; } int main() { //freopen("a.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); if(a==1) insert(b); if(a==2) Delete(b); if(a==3) { int temp=find(b); printf("%d ",temp); } if(a==4) { int temp=findx(b); printf("%d ",temp); } if(a==5) { int temp=findpre(b); printf("%d ",temp); } if(a==6) { int temp=findnext(b); printf("%d ",temp); } } return 0; }