题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 xx 数
- 删除 xx 数(若有多个相同的数,因只删除一个)
- 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
- 查询排名为 xx 的数
- 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
- 求 xx 的后继(后继定义为大于 xx,且最小的数)
输入格式
第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 opt 和 x,opt表示操作的序号( 1≤opt≤6 )
输出格式
对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案
输入输出样例
输入 #1
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出 #1
106465
84185
492737
说明/提示
【数据范围】
对于 %100% 的数据,1≤n≤1e5,∣x∣≤1e7
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define mid ((t[p].l+t[p].r)>>1) 4 using namespace std; 5 const int qs=1e5+7; 6 struct Tree{ 7 ll l,r,dig; 8 }t[qs*4]; 9 struct node{ 10 ll opt,x; 11 }C[qs]; 12 ll n,op,x,B[qs],cnt; 13 void lsh(){//离散化 14 sort(B+1,B+1+cnt); 15 cnt=unique(B+1,B+1+cnt)-B-1; 16 } 17 void Build(int p,int l,int r){ //建树 18 t[p].l=l,t[p].r=r; 19 if(l==r) { 20 t[p].dig=0; 21 return; 22 } 23 Build(p*2,l,mid); 24 Build(p*2+1,mid+1,r); 25 t[p].dig=0; 26 } 27 void Add(int p,int x,ll v){ //增删 28 if(t[p].l==t[p].r){ 29 t[p].dig+=v; 30 return; 31 } 32 if(x<=mid) Add(p*2,x,v); 33 else Add(p*2+1,x,v); 34 t[p].dig=t[p*2+1].dig+t[p*2].dig; //更新 35 } 36 ll Ask(int p,int l,int r){ //区间查询排名 37 if(l<=t[p].l&&r>=t[p].r) return t[p].dig; 38 int val=0; 39 if(l<=mid) val+=Ask(p*2,l,r); 40 if(r>mid) val+=Ask(p*2+1,l,r); 41 return val; 42 } 43 ll frank(int x){ //排名 44 if(x==1) return 1; return (Ask(1,1,x-1)+1); 45 } 46 47 ll kth(int p,int x){ //第k小 48 if(t[p].l==t[p].r) return t[p].l; 49 if(x<=t[p*2].dig) return kth(p*2,x); 50 else return kth(p*2+1,x-t[p*2].dig); 51 } 52 ll kth_Max(int p,int x){ //第k大 53 if(t[p].l==t[p].r) return t[p].l; 54 //k个最大的元素都在右区间 55 if(x<=t[p*2+1].dig) return kth_Max(p*2+1,x); 56 //除去右区间,剩下的第 x-t[p*2+1].dig 大的元素 57 else return kth_Max(p*2,x-t[p*2+1].dig); 58 } 59 int main(){ 60 std::ios::sync_with_stdio(false);cin.tie(0); cout.tie(0); 61 cin>>n; 62 cnt=0; 63 for(int i=1;i<=n;++i){ 64 cin>>C[i].opt>>C[i].x; 65 if(C[i].opt!=4) B[++cnt]=C[i].x; 66 } 67 lsh(); 68 Build(1,1,cnt); 69 for(int i=1;i<=n;++i){ 70 op=C[i].opt,x=C[i].x; 71 if(op!=4) { 72 x=lower_bound(B+1,B+1+cnt,x)-B; 73 } 74 if(op==1) Add(1,x,1); 75 else if(op==2) Add(1,x,-1); 76 else if(op==3) cout<<frank(x)<<" "; 77 else if(op==4) cout<<B[kth(1,x)]<<" "; 78 else if(op==5) cout<<B[kth(1,frank(x)-1)]<<" "; 79 else if(op==6) cout<<B[kth(1,frank(x+1))]<<" "; 80 } 81 return 0; 82 }