Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
【题目分析】
Splay模板题目。
【代码】
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
#define maxn 100005
#define inf (0x3f3f3f3f)
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int ch[maxn][2],fa[maxn],num[maxn],siz[maxn],tim[maxn],rt=0,tot=0;
int ansp,ansn;
void update(int k)
{
siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+tim[k];
}
void rot(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0; else l=1;
r=l^1;
if (y==k) k=x;
else
{
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;
update(y); update(x);
}
void splay(int x,int &k)
{
int y,z;
while (x!=k)
{
y=fa[x];z=fa[y];
if (y!=k)
{
if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x,k);
else rot(y,k);
}
rot(x,k);
}
}
void ins(int &k,int x,int lst)
{
if (!k)
{
k=++tot;
fa[k]=lst;
num[k]=x;
siz[k]=tim[k]=1;
splay(k,rt);
return ;
}
siz[k]++;
if (x==num[k]) tim[k]++;
else if (x<num[k]) ins(ch[k][0],x,k);
else ins(ch[k][1],x,k);
}
void del(int &k,int x)
{
if (x==num[k])
{
if (tim[k]>1)
{
tim[k]--;
siz[k]--;
splay(k,rt);
return ;
}
else
{
if (ch[k][0]*ch[k][1]==0)
{
if ((!ch[k][0])&&(!ch[k][1])) { k=0; return ;}
if (!ch[k][0]) fa[ch[k][1]]=fa[k];
else fa[ch[k][0]]=fa[k];
k=ch[k][0]+ch[k][1];
return ;
}
else
{
int tmp=rand()%2;
rot(ch[k][tmp],k);
del(k,x);
return ;
}
}
}
siz[k]--;
if (num[k]<x) del(ch[k][1],x);
else del(ch[k][0],x);
}
int rank(int k,int x)
{
if (!k) return -inf;
if (num[k]==x) return siz[ch[k][0]];
else if (num[k]>x) return rank(ch[k][0],x);
else return siz[ch[k][0]]+tim[k]+rank(ch[k][1],x);
}
int find(int k,int x)
{
if (siz[ch[k][0]]<x&&siz[ch[k][0]]+tim[k]>=x) return num[k];
else if (siz[ch[k][0]]>=x) return find(ch[k][0],x);
else return find(ch[k][1],x-siz[ch[k][0]]-tim[k]);
}
void pre(int k,int x)
{
if (!k) return ;
if (num[k]<x) {ansp=num[k]; return pre(ch[k][1],x); }
return pre(ch[k][0],x);
}
void nxt(int k,int x)
{
if (!k) return ;
if (num[k]>x) {ansn=num[k]; return nxt(ch[k][0],x); }
return nxt(ch[k][1],x);
}
int main()
{
// freopen("input9.in","r",stdin);
// freopen("output.txt","w",stdout);
srand(20000416);
int m=read();
while (m--)
{
int opt=read(),x=read();
// printf("%d %d\n",opt,x);
switch (opt)
{
case 1: ins(rt,x,0); break;
case 2: del(rt,x); break;
case 3: printf("%d\n",rank(rt,x)+1); break;
case 4: printf("%d\n",find(rt,x)); break;
case 5: pre(rt,x); printf("%d\n",ansp); break;
case 6: nxt(rt,x); printf("%d\n",ansn); break;
}
}
}