Tyvj 1728 普通平衡树
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
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
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
在此总结一下自己容易犯下的错误:
【1】忘记在del函数,insert函数特判时加return
【2】忘记对a[](size)或w[](自己总数)进行操作
【3】忘记加if(v == 0 )的特判(特别是在q_n_r, q_l , q_r的时候)
【4】del时对于旋转操作后向下递归时时tow^1方向
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 200001
#define mod (1 << 31) - 1
using namespace std;
int n;
int ch[M][2] , val[M] , ran[M] , a[M] , w[M] , tot , root;
inline int rand_(){
static int seed = 233;
return seed = int(seed * 48271LL % mod);
}
void maintain(int x){a[x] = w[x] + a[ch[x][0]] + a[ch[x][1]];}
void rotate(int &v , int tow){
int son = ch[v][tow];
ch[v][tow] = ch[son][tow ^ 1];
ch[son][tow ^ 1] = v;
maintain(v);maintain(son);
v = son;
}
void insert(int &v , int val_){
if(!v){
val[v = ++tot] = val_;
ran[v] = rand_();
w[v] = a[v] = 1;
return;
}
++a[v];
if(val[v] == val_){++w[v];return;}
int tow = val_ > val[v];
insert(ch[v][tow] , val_);
if(ran[v] > ran[ch[v][tow]])
rotate(v , tow);
}
void del(int &v , int val_){
if(!v)return;
if(val[v] == val_){
if(w[v] > 1){--a[v] , --w[v];return;}
if(ch[v][1] * ch[v][0] == 0){v = ch[v][1] + ch[v][0];return;}
int tow = ran[ch[v][0]] > ran[ch[v][1]];
rotate(v , tow);
--a[v];
del(ch[v][tow ^ 1] , val_);
return;
}
--a[v];
int tow = val[v] < val_;
del(ch[v][tow] , val_);
}
int ans = 0;
void q_l(int v , int val_){
if(!v)return;
if(val_ > val[v]){ans = val[v];q_l(ch[v][1] , val_);return;}
q_l(ch[v][0] , val_);
}
void q_r(int v , int val_){
if(!v)return;
if(val_ < val[v]){ans = val[v];q_r(ch[v][0] , val_);return;}
q_r(ch[v][1] , val_);
}
int q_r_n(int v , int val_){
if(!v)return -1;
if(a[ch[v][0]] >= val_)return q_r_n(ch[v][0] , val_);
if(a[ch[v][0]] + w[v] < val_)return q_r_n(ch[v][1] , val_ - a[ch[v][0]] - w[v]);
return val[v];
}
int q_n_r(int v , int val_){
if(!v)return 0;
if(val_ > val[v])return q_n_r(ch[v][1] , val_) + w[v] + a[ch[v][0]];
if(val_ < val[v])return q_n_r(ch[v][0] , val_);
return a[ch[v][0]] + 1;
}
int main()
{
scanf("%d",&n);
int y,x;
for(register int i=1;i<=n;i++)
{
scanf("%d%d",&y,&x);
switch(y)
{
case 1:insert(root,x);break;
case 2:del(root,x);break;
case 4:printf("%d\n",q_r_n(root,x));break;
case 3:printf("%d\n",q_n_r(root,x));break;
case 5:ans=0;q_l(root,x);printf("%d\n",ans);break;
case 6:ans=0;q_r(root,x);printf("%d\n",ans);break;
}
}
return 0;
}