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
代码(splay)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
int c[1000005][2],fa[1000005],size[1000005],num[2000005];
int cnt,n,rt,ans;
inline 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;
}
inline void update(int x)
{
int l=c[x][0],r=c[x][1];
size[x]=size[l]+size[r]+1;
}
using namespace std;
void rotate(int x,int &k)
{
int l,r,y=fa[x],z=fa[y];
if (c[y][0]==x) l=0;else l=1;r=l^1;
if (y==k) k=x;
else if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
fa[x]=z;fa[y]=x;
fa[c[x][r]]=y;c[y][l]=c[x][r];
c[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 (c[z][0]==y^c[y][0]==x) rotate(x,k);else rotate(y,k);
}
rotate(x,k);
}
}
void insert(int &k,int x,int f)
{
if (k==0){k=++cnt;num[k]=x;fa[k]=f;size[k]=1;splay(k,rt);return;}
if (x>=num[k]) insert(c[k][1],x,k);else insert(c[k][0],x,k);
}
void find(int k,int x)
{
if (k==0) return;
if (num[k]==x){ans=k;find(c[k][0],x);return;}
if (num[k]>x) find(c[k][0],x);else find(c[k][1],x);
}
void query_before(int k,int x)
{
if (k==0) return;
if (num[k]<x) {ans=k;query_before(c[k][1],x);}
else query_before(c[k][0],x);
}
void query_after(int k,int x)
{
if (k==0) return;
if (num[k]>x) {ans=k;query_after(c[k][0],x);}
else query_after(c[k][1],x);
}
void cl(int &x)
{
if (c[x][0]) cl(c[x][0]);
else if (c[x][1]) cl(c[x][1]);
else ans=fa[x],x=0;
}
void del(int x)
{
ans=0;
query_before(rt,x);
int x1=ans;
ans=0;
query_after(rt,x);
int x2=ans;
splay(x1,rt);splay(x2,c[rt][1]);
cl(x2);
splay(ans,rt);
}
int query_rank(int x)
{
ans=0;
find(rt,x);
x=ans;
if (x!=0) splay(x,rt);
return size[c[x][0]];
}
int query_num(int k,int x)
{
int l=c[k][0],r=c[k][1];
if (size[l]+1==x) return k;
if (size[l]>=x) return query_num(l,x);else return query_num(r,x-size[l]-1);
}
int main()
{
n=read();
int opt,x;
insert(rt,-2000000001,0);
insert(rt,2000000001,0);
while (n--)
{
opt=read();x=read();
if (opt==1) insert(rt,x,0);
if (opt==2) del(x);
if (opt==3) printf("%d\n",query_rank(x));
if (opt==4) printf("%d\n",num[query_num(rt,x+1)]);
if (opt==5)
{
query_before(rt,x);
printf("%d\n",num[ans]);
}
if (opt==6)
{
query_after(rt,x);
printf("%d\n",num[ans]);
}
}
return 0;
}
代码(treap)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1000005
int n,cnt,rt,ans;
int size[N],sum[N],rnd[N],num[N],ls[N],rs[N];
inline 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;
}
inline void update(int k)
{
size[k]=size[ls[k]]+size[rs[k]]+sum[k];
}
inline void lturn(int &k)
{
int t=rs[k];rs[k]=ls[t];ls[t]=k;
size[t]=size[k];update(k);k=t;
}
inline void rturn(int &k)
{
int t=ls[k];ls[k]=rs[t];rs[t]=k;
size[t]=size[k];update(k);k=t;
}
using namespace std;
void insert(int &k,int x)
{
if (k==0){k=++cnt;size[k]=1;num[k]=x;sum[k]=1;rnd[k]=rand();return;}
size[k]++;
if (num[k]==x)sum[k]++;
else if (x>num[k])
{
insert(rs[k],x);
if (rnd[rs[k]]<rnd[k])lturn(k);
}
else
{
insert(ls[k],x);
if (rnd[ls[k]]<rnd[k])rturn(k);
}
}
void del(int &k,int x)
{
if (k==0) return;
if (num[k]==x)
{
if (sum[k]>1)
{
sum[k]--;size[k]--;return;
}
if (rs[k]*ls[k]==0) k=rs[k]+ls[k];
else if (rnd[ls[k]]<rnd[rs[k]])
rturn(k),del(k,x);
else lturn(k),del(k,x);
}
else if (x>num[k])
size[k]--,del(rs[k],x);
else size[k]--,del(ls[k],x);
}
int query_rank(int k,int x)
{
if (k==0) return 0;
if (num[k]==x) return size[ls[k]]+1;
else if (x>num[k])
return size[ls[k]]+sum[k]+query_rank(rs[k],x);
else return query_rank(ls[k],x);
}
int query_num(int k,int x)
{
if (k==0) return 0;
if (x<=size[ls[k]]) return query_num(ls[k],x);
else if (x>size[ls[k]]+sum[k])
return query_num(rs[k],x-size[ls[k]]-sum[k]);
else return num[k];
}
void query_pro(int k,int x)
{
if (k==0) return;
if (num[k]<x)ans=k,query_pro(rs[k],x);
else query_pro(ls[k],x);
}
void query_sub(int k,int x)
{
if (k==0) return;
if (num[k]>x)ans=k,query_sub(ls[k],x);
else query_sub(rs[k],x);
}
int main()
{
n=read();
int opt,x;
while (n--)
{
opt=read();x=read();
switch(opt)
{
case 1:insert(rt,x);break;
case 2:del(rt,x);break;
case 3:printf("%d\n",query_rank(rt,x));break;
case 4:printf("%d\n",query_num(rt,x));break;
case 5:ans=0;query_pro(rt,x);printf("%d\n",num[ans]);break;
case 6:ans=0;query_sub(rt,x);printf("%d\n",num[ans]);break;
}
}
return 0;
}