洛谷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 5\cdot {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\n",BIT.qrank(e[i].opl-1,e[i].opr,e[i].opk,0)+1);
109         else if(e[i].op==2)printf("%d\n",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\n",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\n",BIT.qnum(e[i].opl-1,e[i].opr,tmp+1));
120         }
121     }
122 }

 

posted @ 2018-01-07 20:38  Echo宝贝儿  阅读(280)  评论(1编辑  收藏  举报