【题目】
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
Sample Output
106465 84185 492737
HINT
n 的数据范围:n ≤ 100000
每个数的数据范围:[ , ]
【分析】
平衡树板子题。。。
就是常规的平衡树操作,我就得 要比 好写一点,就写的
【代码】
#include<ctime>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define inf (int)2e+9
#define lc(x) son[x][0]
#define rc(x) son[x][1]
using namespace std;
int tot,val[N],num[N],size[N],weight[N],son[N][2];
void pushup(int root)
{
size[root]=size[lc(root)]+size[rc(root)]+num[root];
}
void rotate(int &root,int t)
{
int x=son[root][t];
son[root][t]=son[x][t^1];
son[x][t^1]=root;
pushup(root),pushup(x);
root=x;
}
void insert(int &root,int x)
{
if(root)
{
if(val[root]==x)
num[root]++;
else
{
int t=val[root]<x;
insert(son[root][t],x);
if(weight[son[root][t]]<weight[root])
rotate(root,t);
}
}
else
{
root=++tot;
val[tot]=x;
num[tot]=1;
weight[tot]=rand();
}
pushup(root);
}
void remove(int &root,int x)
{
if(val[root]==x)
{
if(num[root]>1)
num[root]--;
else
{
if(!lc(root)&&!rc(root))
{
root=0;
return;
}
rotate(root,weight[lc(root)]<weight[rc(root)]);
remove(root,x);
}
}
else
remove(son[root][val[root]<x],x);
pushup(root);
}
int findrank(int root,int x)
{
if(!root) return 0;
if(val[root]<x) return size[lc(root)]+num[root]+findrank(rc(root),x);
return findrank(lc(root),x);
}
int findkth(int root,int x)
{
if(size[lc(root)]<x&&size[lc(root)]+num[root]>=x) return val[root];
if(x<=size[lc(root)]) return findkth(lc(root),x);
return findkth(rc(root),x-size[lc(root)]-num[root]);
}
int findpre(int root,int x)
{
if(!root) return -inf;
if(val[root]<x) return max(val[root],findpre(rc(root),x));
return findpre(lc(root),x);
}
int findsuf(int root,int x)
{
if(!root) return inf;
if(val[root]>x) return min(val[root],findsuf(lc(root),x));
return findsuf(rc(root),x);
}
int main()
{
int n,i,s,x,root=0;
srand(time(0));
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%d%d",&s,&x);
if(s==1) insert(root,x);
if(s==2) remove(root,x);
if(s==3) printf("%d\n",findrank(root,x)+1);
if(s==4) printf("%d\n",findkth(root,x));
if(s==5) printf("%d\n",findpre(root,x));
if(s==6) printf("%d\n",findsuf(root,x));
}
return 0;
}