您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
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.每个数的数据范围:[-2e9,2e9]
//#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int M = 1000000+7;
struct node
{
int c,x;
}lx[M];
int a[M],b[M],la[M];
int mp[M];//最后要输出的表
int st[M<<2];
void update(int l,int r,int rt,int x,int d)
{
if(l==r)
{
st[rt]+=d;
return ;
}
int mid=(l+r)/2;
if(x<=mid)update(l,mid,rt<<1,x,d);
else update(mid+1,r,rt<<1|1,x,d);
st[rt]=st[rt<<1]+st[rt<<1|1];
}
int xrank(int l,int r,int rt,int L,int R)
{
if(L<=l&&r<=R)
{
return st[rt];
}
int mid=(l+r)/2;
int res=0;
if(L<=mid)res+=xrank(l,mid,rt<<1,L,R);
if(R>mid)res+=xrank(mid+1,r,rt<<1|1,L,R);
return res;
}
int Kith(int l, int r,int rt,int k)
{
if(l==r)return l;// l表示的是权值
int mid=(l+r)>>1;
if(st[rt<<1]>=k)return Kith(l,mid,rt<<1,k);
return Kith(mid+1,r,rt<<1|1,k-st[rt<<1]);
}
int Findpre(int p,int l,int r)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(st[p<<1|1])return Findpre(p<<1|1,mid+1,r);//右子树非空向右找
return Findpre(p<<1,l,mid);//否则向左找
}
//找前驱 尽可能在小于v的右子树找
int Pre(int p,int l,int r,int v)
{
if(r<v)//maxr<v即在p的子树中 p区间内最右非空子树即答案
{
if(st[p])return Findpre(p,l,r);
return 0;
}
int mid=(l+r)>>1,Re;
//如果v在右子树可能有前驱(至少mid+1比v小)就先查右子树,l=mid+1
if(mid+1<v&&st[p<<1|1]&&(Re=Pre(p<<1|1,mid+1,r,v)))return Re;
//否则查左子树,r=mid,使r不断变小直至满足题意小于v
return Pre(p<<1,l,mid,v);
}
int Findnext(int p,int l,int r)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(st[p<<1])return Findnext(p<<1,l,mid);
return Findnext(p<<1|1,mid+1,r);
}
//找后继 尽可能在大于v的左子树找
int Next(int p,int l,int r,int v)
{
if(v<l)//已找到大于v的最小完整区间
{
if(st[p])return Findnext(p,l,r);
return 0;
}
int mid=(l+r)>>1,Re;
//如果左子树里有比v大的(至少mid比v大)就查左子树 否则查右子树
if(v<mid&&st[p<<1]&&(Re=Next(p<<1,l,mid,v)))return Re;
return Next(p<<1|1,mid+1,r,v);
}
int main()
{
int n,N=100000;
cin>>n;
int c,x;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&c,&x);
lx[i].x=x;
lx[i].c=c;
b[i]=a[i]=x;
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
la[i]=lower_bound(b+1,b+1+n,a[i])-b;
mp[la[i]]=a[i];
// printf("%d %d\n",la[i],mp[la[i]]);
}
for(int i=1;i<=n;i++)
{
c=lx[i].c;
x=la[i];
if(c==1)update(1,N,1,x,1);//插入x
if(c==2)update(1,N,1,x,-1);//删除x
if(c==3)printf("%d\n",xrank(1,N,1,1,x-1)+1);//查询x的排名-从小到大
if(c==4)x=lx[i].x,printf("%d\n",mp[Kith(1,N,1,x)]);//查询第k小
if(c==5)printf("%d\n",mp[Pre(1,1,N,x)]);//查询x的前驱
if(c==6)printf("%d\n",mp[Next(1,1,N,x)]);//查询x的后继
}
return 0;
}