• 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)


    P3380 【模板】二逼平衡树(树套树)

    题目描述

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

    1. 查询k在区间内的排名

    2. 查询区间内排名为k的值

    3. 修改某一位值上的数值

    4. 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)

    5. 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)

    注意上面两条要求和tyvj或者bzoj不一样,请注意

    输入输出格式

    输入格式:

    第一行两个数 n,m 表示长度为n的有序序列和m个操作

    第二行有n个数,表示有序序列

    下面有m行,opt表示操作标号

    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名

    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数

    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k

    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱

    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    输出格式:

    对于操作1,2,4,5各输出一行,表示查询结果

    输入输出样例

    输入样例#1: 复制
    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5
    输出样例#1: 复制
    2
    4
    3
    4
    9

    说明

    时空限制:2s,128M

    n,m leq 5cdot {10}^4n,m5104 保证有序序列所有值在任何时刻满足 [0, {10} ^8][0,108]

    题目来源:bzoj3196 / Tyvj1730 二逼平衡树,在此鸣谢

    此数据为洛谷原创。(特别提醒:此数据不保证操作5、6一定存在,故请务必考虑不存在的情况)

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #define maxn 50010
      5 #define maxm 50010*400
      6 using namespace std;
      7 int n,m,tot,root[maxn],a[maxn],hash[maxn*2],A[20],B[20];
      8 struct node{int op,opl,opr,opk;}e[maxn];
      9 struct S_T{
     10     int cnt,lc[maxm],rc[maxm],sum[maxm];
     11     void insert(int &k,int l,int r,int pos,int w){
     12         if(!k)k=++cnt;
     13         sum[k]+=w;
     14         if(l==r)return;
     15         int mid=(l+r)>>1;
     16         if(pos<=mid)insert(lc[k],l,mid,pos,w);
     17         else insert(rc[k],mid+1,r,pos,w);
     18     }
     19     int getrank(int l,int r,int w,bool ty){
     20         int tmp=0;
     21         if(l==r){
     22             if(!ty)return 0;
     23             else{
     24                 for(int i=1;i<=A[0];i++)tmp+=sum[A[i]];
     25                 for(int i=1;i<=B[0];i++)tmp-=sum[B[i]];
     26                 return tmp;
     27             }
     28         }
     29         for(int i=1;i<=A[0];i++)tmp+=sum[lc[A[i]]];
     30         for(int i=1;i<=B[0];i++)tmp-=sum[lc[B[i]]];
     31         int mid=(l+r)>>1;
     32         if(w<=mid){
     33             for(int i=1;i<=A[0];i++)A[i]=lc[A[i]];
     34             for(int i=1;i<=B[0];i++)B[i]=lc[B[i]];
     35             return getrank(l,mid,w,ty);
     36         }
     37         else {
     38             for(int i=1;i<=A[0];i++)A[i]=rc[A[i]];
     39             for(int i=1;i<=B[0];i++)B[i]=rc[B[i]];
     40             return tmp+getrank(mid+1,r,w,ty);
     41         }
     42     }
     43     int getnum(int l,int r,int w){
     44         if(l==r)return hash[l];
     45         int tmp=0;
     46         for(int i=1;i<=A[0];i++)tmp+=sum[lc[A[i]]];
     47         for(int i=1;i<=B[0];i++)tmp-=sum[lc[B[i]]];
     48         int mid=(l+r)>>1;
     49         if(w<=tmp){
     50             for(int i=1;i<=A[0];i++)A[i]=lc[A[i]];
     51             for(int i=1;i<=B[0];i++)B[i]=lc[B[i]];
     52             return getnum(l,mid,w);
     53         }
     54         else{
     55             for(int i=1;i<=A[0];i++)A[i]=rc[A[i]];
     56             for(int i=1;i<=B[0];i++)B[i]=rc[B[i]];
     57             return getnum(mid+1,r,w-tmp);
     58         }
     59     }
     60 }ST;
     61 struct B_I_T{
     62     void add(int pos,int key,int val){
     63         while(pos<=n){
     64             ST.insert(root[pos],1,tot,key,val);
     65             pos+=pos&(-pos);
     66         }
     67     }
     68     int qrank(int l,int r,int k,bool ty){
     69         A[0]=0;while(r)A[++A[0]]=root[r],r-=r&(-r);
     70         B[0]=0;while(l)B[++B[0]]=root[l],l-=l&(-l);
     71         return ST.getrank(1,tot,k,ty);
     72     }
     73     int qnum(int l,int r,int k){
     74         A[0]=0;while(r)A[++A[0]]=root[r],r-=r&(-r);
     75         B[0]=0;while(l)B[++B[0]]=root[l],l-=l&(-l);
     76         return ST.getnum(1,tot,k);
     77     }
     78     void modify(int pos,int w){
     79         A[0]=0;int tmp=pos;
     80         while(pos<=n)A[++A[0]]=pos,pos+=pos&(-pos);
     81         for(int i=1;i<=A[0];i++)ST.insert(root[A[i]],1,tot,a[tmp],-1);
     82         for(int i=1;i<=A[0];i++)ST.insert(root[A[i]],1,tot,w,1);
     83         a[tmp]=w;
     84     }
     85 }BIT;
     86 int main(){
     87     scanf("%d%d",&n,&m);
     88     for(int i=1;i<=n;i++)scanf("%d",&a[i]),hash[i]=a[i];
     89     int opt,l,r,k,tmp=n;
     90     for(int i=1;i<=m;i++){
     91         scanf("%d",&opt);
     92         if(opt==3)scanf("%d%d",&l,&k);
     93         else scanf("%d%d%d",&l,&r,&k);
     94         e[i].op=opt;e[i].opl=l;e[i].opk=k;
     95         if(opt!=3)e[i].opr=r;
     96         if(opt!=2)hash[++tmp]=k;
     97     }
     98     sort(hash+1,hash+tmp+1);
     99     tot=unique(hash+1,hash+tmp+1)-(hash+1);
    100     for(int i=1;i<=n;i++){
    101         a[i]=lower_bound(hash+1,hash+tot+1,a[i])-hash;
    102         BIT.add(i,a[i],1);
    103     }
    104     for(int i=1;i<=m;i++)
    105     if(e[i].op!=2)e[i].opk=lower_bound(hash+1,hash+tot+1,e[i].opk)-hash;
    106     
    107     for(int i=1;i<=m;i++){
    108         if(e[i].op==1)printf("%d
    ",BIT.qrank(e[i].opl-1,e[i].opr,e[i].opk,0)+1);
    109         else if(e[i].op==2)printf("%d
    ",BIT.qnum(e[i].opl-1,e[i].opr,e[i].opk));
    110         else if(e[i].op==3)BIT.modify(e[i].opl,e[i].opk);
    111         else if(e[i].op==4){
    112             int tmp=BIT.qrank(e[i].opl-1,e[i].opr,e[i].opk,0);
    113             if(!tmp)puts("-2147483647");
    114             else printf("%d
    ",BIT.qnum(e[i].opl-1,e[i].opr,tmp));
    115         }
    116         else{
    117             int tmp=BIT.qrank(e[i].opl-1,e[i].opr,e[i].opk,1);
    118             if(tmp==e[i].opr-e[i].opl+1)puts("2147483647");
    119             else printf("%d
    ",BIT.qnum(e[i].opl-1,e[i].opr,tmp+1));
    120         }
    121     }
    122 }
  • 相关阅读:
    正则匹配中 ^ $ 和  的区别
    jQuery 选择同时包含两个class的元素的实现方法
    JSON—去除JSON数据中的所有HTML标…
    HTML5 自定义属性 data-*属性名一定要小写吗?
    Java线程池(ExecutorService)使用
    ExecutorService中submit和execute的区别
    启用Microsoft loopback Adapte
    【Spring】如何配置多个applicationContext.xml文件
    C#编程之AES加密(一)
    C#编程之利用C#创建dll并调用(三)
  • 原文地址:https://www.cnblogs.com/thmyl/p/8231634.html
Copyright © 2020-2023  润新知