• 权值线段树模板(自用)


    题目描述

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

    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)<<"
    ";
    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 }
  • 相关阅读:
    python map 详解
    python 中的集合(set) 详解
    python中的列表(list) 切片详解
    django 创建数据库表 命令
    django如何检查创建的模型(model)是否有语法错误或者逻辑错误
    python 列表(list)去除重复的元素总结
    python中的 zip函数详解
    django post和get 比较
    正则表达式的特殊符号和字符详细解析
    .NET/MVC-发布到IIS6.1提示未能加载程序集System.Web.Http.WebHost
  • 原文地址:https://www.cnblogs.com/Suki-Sugar/p/14629298.html
Copyright © 2020-2023  润新知