权值线段树模板(自用)

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 xx 数
  2. 删除 xx 数(若有多个相同的数,因只删除一个)
  3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
  4. 查询排名为 xx 的数
  5. 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
  6. 求 xx 的后继(后继定义为大于 xx,且最小的数)

输入格式

第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 opt 和 xopt表示操作的序号( 1opt6 )

输出格式

对于操作 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% 的数据,1n1e5,x1e7

 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)<<"\n";
77         else if(op==4) cout<<B[kth(1,x)]<<"\n";
78         else if(op==5) cout<<B[kth(1,frank(x)-1)]<<"\n";
79         else if(op==6) cout<<B[kth(1,frank(x+1))]<<"\n";
80     }    
81     return 0;
82 }

 

posted @ 2021-04-07 19:59  Suki_Sugar  阅读(71)  评论(0编辑  收藏  举报
Live2D