【题目描述】:
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个)
-
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)
【输入描述】:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)。
【输出描述】:
对于操作3,4,5,6每行输出一个数,表示对应答案。
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<set>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
struct Node{
int l,r,v,d,cnt,s;
}a[100010];
int tot,root,n,inf=1e9;
int read(){
char c;int w,f;w=0;f=1;c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
w=w*10+c-'0';c=getchar();
}
return w*f;
}
int New(int v){
a[++tot].v=v;
a[tot].d=rand();
a[tot].cnt=a[tot].s=1;
return tot;
}
void updata(int p){
a[p].s=a[a[p].l].s+a[a[p].r].s+a[p].cnt;
}
void build(){
New(-inf);New(inf);
root=1;a[1].r=2;
updata(root);
}
int get1(int p,int v){
if(p==0) return 0;
if(v==a[p].v) return a[a[p].l].s+1;
if(v<a[p].v) return get1(a[p].l,v);
return get1(a[p].r,v)+a[a[p].l].s+a[p].cnt;
}
int get2(int p,int rank){
if(p==0) return inf;
if(a[a[p].l].s>=rank) return get2(a[p].l,rank);
if(a[a[p].l].s+a[p].cnt>=rank) return a[p].v;
return get2(a[p].r,rank-a[a[p].l].s-a[p].cnt);
}
void zig(int &p){
int q=a[p].l;
a[p].l=a[q].r;a[q].r=p;p=q;
updata(a[p].r);updata(p);
}
void zag(int &p){
int q=a[p].r;
a[p].r=a[q].l;a[q].l=p;p=q;
updata(a[p].l);updata(p);
}
void insert(int &p,int v){
if(p==0){
p=New(v);
return ;
}
if(v==a[p].v){
a[p].cnt++;updata(p);return ;
}
if(v<a[p].v){
insert(a[p].l,v);
if(a[p].d<a[a[p].l].d) zig(p);
}
else{
insert(a[p].r,v);
if(a[p].d<a[a[p].r].d) zag(p);
}
updata(p);
}
int get3(int v){
int ans=1;
int p=root;
while(p){
if(v==a[p].v){
if(a[p].l>0){
p=a[p].l;
while(a[p].r>0) p=a[p].r;
ans=p;
}
break;
}
if(a[p].v<v&&a[p].v>a[ans].v) ans=p;
p=v<a[p].v?a[p].l:a[p].r;
}
return a[ans].v;
}
int get4(int v){
int ans=2;
int p=root;
while(p){
if(v==a[p].v){
if(a[p].r>0){
p=a[p].r;
while(a[p].l>0) p=a[p].l;
ans=p;
}
break;
}
if(a[p].v>v&&a[p].v<a[ans].v) ans=p;
p=v<a[p].v?a[p].l:a[p].r;
}
return a[ans].v;
}
void remove(int &p,int v){
if(p==0){
return ;
}
if(v==a[p].v){
if(a[p].cnt>1){
a[p].cnt--;updata(p);return ;
}
if(a[p].l||a[p].r){
if(a[p].r==0||a[a[p].l].d>a[a[p].r].d){
zig(p);remove(a[p].r,v);
}
else{
zag(p);remove(a[p].l,v);
}
updata(p);
}
else p=0;
return ;
}
v<a[p].v?remove(a[p].l,v):remove(a[p].r,v);
updata(p);
}
int main(){
// freopen("p3369.in","r",stdin);
// freopen("p3369.out","w",stdout);
build();
//int kb;kb=0;
cin>>n;//n=read();
while(n--){
int po,x;
/* if(kb==22){
printf("11111 %d\n",po);
} */
cin>>po>>x;//o=read();x=read();
if(po==1){
insert(root,x);
continue;
}
if(po==2){
remove(root,x);
continue;
}
if(po==3){
printf("%d\n",get1(root,x)-1);//kb++;
continue;
}
if(po==4){
printf("%d\n",get2(root,x+1));//kb++;
continue;
}
if(po==5){
printf("%d\n",get3(x));//kb++;
continue;
}
if(po==6){
printf("%d\n",get4(x));//kb++;
continue;
}
}
return 0;
}