问题描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求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]
分析:
模板题,不多bb
特判一下查询排名1的数,不然死循环
前驱和后继用了rank+kth代替,不过调用了两个函数,
(也有一个函数直接求的方法,应该比这样快,但是没这个无脑)
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
const int maxm=3e5+5;
struct Query{
int d,x;
}q[maxm];
int a[maxm<<2];
int xx[maxm],num;
void build(int l,int r,int node){
a[node]=0;
if(l==r)return ;
int mid=(l+r)/2;
build(l,mid,node*2);
build(mid+1,r,node*2+1);
}
void update(int x,int val,int l,int r,int node){
a[node]+=val;
if(l==r)return ;
int mid=(l+r)/2;
if(x<=mid)update(x,val,l,mid,node*2);
else update(x,val,mid+1,r,node*2+1);
}
int ask(int st,int ed,int l,int r,int node){
if(st<=l&&ed>=r)return a[node];
int mid=(l+r)/2;
int ans=0;
if(st<=mid)ans+=ask(st,ed,l,mid,node*2);
if(ed>=mid+1)ans+=ask(st,ed,mid+1,r,node*2+1);
return ans;
}
int kth(int k,int l,int r,int node){
if(l==r)return l;
int mid=(l+r)/2;
if(a[node*2]>=k)return kth(k,l,mid,node*2);
return kth(k-a[node*2],mid+1,r,node*2+1);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>q[i].d>>q[i].x;
if(q[i].d!=4){
xx[++num]=q[i].x;
}
}
sort(xx+1,xx+1+num);
num=unique(xx+1,xx+1+num)-xx-1;
build(1,num,1);
for(int i=1;i<=n;i++){
int d=q[i].d;
int x=q[i].x;
if(d!=4)x=lower_bound(xx+1,xx+1+num,x)-xx;
if(d==1){//插入
update(x,1,1,num,1);
}else if(d==2){//删除
update(x,-1,1,num,1);
}else if(d==3){//x的排名
cout<<(x-1?ask(1,x-1,1,num,1)+1:1)<<endl;//如果x-1等于0则排名为1
}else if(d==4){//排第x的
cout<<xx[kth(x,1,num,1)]<<endl;
}else if(d==5){//前驱
int p=ask(1,x-1,1,num,1);
cout<<xx[kth(p,1,num,1)]<<endl;
}else{//后继
int p=ask(1,x,1,num,1);
cout<<xx[kth(p+1,1,num,1)]<<endl;
}
}
return 0;
}