您需要写一种数据结构(可参考题目标题,但是这句话其实并没有什么用233),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int size[200009],fa[200009],v[200009],ch[200009][2],cnt[200009],rt,tot;
int n,pree,nextt;
inline int read()
{
int f=1,ans;
char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;
ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
void up(int i)
{
size[i]=cnt[i]+size[ch[i][0]]+size[ch[i][1]];
}
void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (z)
if (ch[z][0]==y)ch[z][0]=x;else ch[z][1]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
void splay(int x,int k)
{
int y,z;
while (fa[x]!=k)
{
y=fa[x],z=fa[y];
if (z!=k)
if ((ch[z][0]==y)^(ch[y][0]==x))rotate(x);else rotate(y);
rotate(x);
}
if (k==0) rt=x;
up(x);
}
void insert(int i,int x)
{
if (rt==0)
{
rt=++tot;
v[tot]=x;
size[tot]=cnt[tot]=1;
return;
}
int y;
while (true)
{
if (v[i]==x) {cnt[i]++;up(i);break;};//在插入和删除之后,一定要注意up
y=ch[i][v[i]<x];
if (y==0)
{
v[++tot]=x;
cnt[tot]=1;
ch[i][v[i]<x]=tot;
fa[tot]=i;
size[tot]=1;
i=tot;
break;
}
i=y;
}
splay(i,0);
}
int find(int i,int x)
{
if (i==0) return 0;
if (v[i]==x) return i;
if (v[i]>x) return find(ch[i][0],x);
else return find(ch[i][1],x);
up(i);
}
void del(int x)
{
int k=find(rt,x);
if (k==0) return;
x=k;
splay(x,0);
if (cnt[x]>1){cnt[x]--;up(x);return;}//只要有更新就要有up ,并且,可能需要删除的数有多个,那么就删除一个,因为这个地方
if(ch[x][0]==0&&ch[x][1]==0) {rt=0;return;}//wa了无数次,调整心态,加油
if(ch[x][0]==0){rt=ch[x][1];fa[ch[x][1]]=0;return;}
if(ch[x][1]==0){rt=ch[x][0];fa[ch[x][0]]=0;return;}
int y=ch[x][0];
while (ch[y][1])y=ch[y][1];
splay(y,x);rt=y;
ch[y][1]=ch[x][1];fa[y]=0;fa[ch[x][1]]=y;up(y);//少了一个up,这个不能丢啊,删除后要更新
}
void find_pre(int i,int x)
{
if (i==0) return;
if (v[i]>=x) find_pre(ch[i][0],x);
else {pree=v[i];find_pre(ch[i][1],x);}
up(i);
}
void find_next(int i,int x)
{
if (i==0) return;
if (v[i]<=x) find_next(ch[i][1],x);
else {nextt=v[i];find_next(ch[i][0],x);}
up(i);
}
int find_rank(int x)
{
int ans=0,now=rt;//有可能
while (now)
{
if (v[now]==x) return size[ch[now][0]]+ans+1;
else if (v[now]>x) now=ch[now][0];
else ans+=cnt[now]+size[ch[now][0]],now=ch[now][1];
}
return ans;
}
int find_kth(int i,int k)
{
if (i==0) return 0;
if (size[ch[i][0]]>=k) return find_kth(ch[i][0],k);
else
if (size[ch[i][0]]+cnt[i]>=k) return v[i];
else return find_kth(ch[i][1],k-size[ch[i][0]]-cnt[i]);
}
int main()
{
n=read();
while (n--)
{
int k,x,y;
k=read();x=read();
size[0]=0;
switch(k)
{
case 1:insert(rt,x);break;
case 2:del(x);break;
case 3:printf("%d\n",find_rank(x));break;
case 4:printf("%d\n",find_kth(rt,x));break;
case 5:find_pre(rt,x);printf("%d\n",pree);break;
case 6:find_next(rt,x);printf("%d\n",nextt);break;
}
}
return 0;
}