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
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
Solution
请参考题目名:普通平衡树
那就打个平衡树呗
我打的splay
六个操作分别维护即可,裸的
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1010000
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,t[N][2],g[N],size[N],fa[N],tot,root,siz[N];
int lr(int x){return x==t[fa[x]][1];}
void update(int x){size[x]=size[t[x][0]]+size[t[x][1]]+siz[x];}
void rotate(int x)
{
int y=fa[x],k=lr(x);
t[y][k]=t[x][1-k];
if(t[x][1-k]) fa[t[x][1-k]]=y;
fa[x]=fa[y];
if(fa[y]) t[fa[y]][lr(y)]=x;
t[x][1-k]=y;fa[y]=x;
update(y);update(x);
}
void splay(int x,int y)
{
if(x==y) return;
while(fa[x]!=y)
{
if(fa[fa[x]]!=y)
if(lr(x)==lr(fa[x])) rotate(fa[x]);
else rotate(x);
rotate(x);
}
if(y==0) root=x;
}
int kth(int x)
{
int y=root;
while(g[y]!=x)
{
if(x<g[y]) y=t[y][0];else y=t[y][1];
}
return y;
}
int xth(int x,int y)
{
if(size[t[y][0]]+siz[y]>=x&&size[t[y][0]]<x) return y;
if(x<=size[t[y][0]]) return xth(x,t[y][0]);
else return xth(x-size[t[y][0]]-siz[y],t[y][1]);
}
int kthsmall(int x,int y)
{
if(y==0) return -2147483647;
if(x>g[y]) return max(g[y],kthsmall(x,t[y][1]));
else return kthsmall(x,t[y][0]);
}
int kthbig(int x,int y)
{
if(y==0) return 2147483647;
if(x<g[y]) return min(g[y],kthbig(x,t[y][0]));
else return kthbig(x,t[y][1]);
}
void put(int y,int z,int x)
{
splay(y,0);splay(z,y);
if(t[z][0]!=0) siz[t[z][0]]++;
else
{
g[++tot]=x;t[z][0]=tot;fa[tot]=z;
size[tot]=siz[tot]=1;
}
update(t[z][0]);update(z);update(y);
}
int main()
{
scanf("%d",&n);
tot=2;g[1]=-2147483647;size[1]=2;root=1;
g[2]=2147483647;size[2]=siz[2]=siz[1]=1;fa[2]=1;t[1][1]=2;
fo(i,1,n)
{
int opt,x;scanf("%d%d",&opt,&x);
if(opt==1)//插入x
{
int jy1=kthsmall(x,root);
int jy2=kthbig(x,root);
jy1=kth(jy1);jy2=kth(jy2);
put(jy1,jy2,x);
}
if(opt==2)//删除x
{
int jy1=kthsmall(x,root);
int jy2=kthbig(x,root);
jy1=kth(jy1);jy2=kth(jy2);
splay(jy1,0);splay(jy2,jy1);
siz[t[jy2][0]]--;update(t[jy2][0]);
if(siz[t[jy2][0]]==0) t[jy2][0]=0;
update(jy2);update(jy1);
}
if(opt==3)//查询x排名
{
int jy=kth(x);
splay(jy,0);
printf("%d\n",size[t[jy][0]]);
}
if(opt==4)//查询排名x的数
{
printf("%d\n",g[xth(x+1,root)]);
}
if(opt==5)//小于x的最大数
{
int jy=kthsmall(x,root);
printf("%d\n",jy);
}
if(opt==6)//大于x的最小数
{
int jy=kthbig(x,root);
printf("%d\n",jy);
}
}
}