bzoj3196 Tyvj 1730 二逼平衡树

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 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的后继

Output

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

Sample Input

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

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数。
 
正解:树状数组套主席树。
这题真的二逼woc。。我最后加了一个特判才过。。
其他的都一样,查询排名就是小于它的数的个数+1。查询前驱就是小于等于它的数减一(其实不一定减一,代码里有特判),然后再变成查询区间第k小,查询后继类似。
 
  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <vector>
  9 #include <cmath>
 10 #include <queue>
 11 #include <stack>
 12 #include <map>
 13 #include <set>
 14 #define N (50005)
 15 #define il inline
 16 #define RG register
 17 #define ll long long
 18 #define lb(x) (x & -x)
 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 20 
 21 using namespace std;
 22 
 23 struct node{ int type,l,r,k; }q[N];
 24 
 25 int sum[200*N],ls[200*N],rs[200*N],rt[N],q1[110],q2[110],a[N],last[N],hsh[2*N],n,m,sz,tot,ans;
 26 
 27 il int gi(){
 28     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
 29     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
 30 }
 31 
 32 il void update(RG int x,RG int &y,RG int l,RG int r,RG int v,RG int fg){
 33     if (!y) y=++sz; sum[y]=sum[x]+fg,ls[y]=ls[x],rs[y]=rs[x];
 34     if (l==r) return; RG int mid=(l+r)>>1;
 35     v<=mid ? update(ls[x],ls[y],l,mid,v,fg) : update(rs[x],rs[y],mid+1,r,v,fg);
 36 }
 37 
 38 il int queryrank(RG int x,RG int l,RG int r,RG int v){
 39     if (l==r) return 0; RG int mid=(l+r)>>1;
 40     return v<=mid ? queryrank(ls[x],l,mid,v) : queryrank(rs[x],mid+1,r,v)+sum[ls[x]];
 41 }
 42 
 43 il int querypre(RG int x,RG int l,RG int r,RG int v){
 44     if (l==r) return sum[x] ? sum[x]-1 : 0; RG int mid=(l+r)>>1; //特判,如果当前数存在才减一
 45     return v<=mid ? querypre(ls[x],l,mid,v) : querypre(rs[x],mid+1,r,v)+sum[ls[x]];
 46 }
 47 
 48 il int querynext(RG int x,RG int l,RG int r,RG int v){
 49     if (l==r) return sum[x] ? sum[x]-1 : 0; RG int mid=(l+r)>>1;
 50     return v<=mid ? querynext(ls[x],l,mid,v)+sum[rs[x]] : querynext(rs[x],mid+1,r,v);
 51 }
 52 
 53 il int querykth1(RG int tot1,RG int tot2,RG int l,RG int r,RG int k){
 54     if (l==r) return hsh[l]; RG int mid=(l+r)>>1,tmp=0;
 55     for (RG int i=1;i<=tot1;++i) tmp-=sum[ls[q1[i]]];
 56     for (RG int i=1;i<=tot2;++i) tmp+=sum[ls[q2[i]]];
 57     if (k<=tmp){
 58     for (RG int i=1;i<=tot1;++i) q1[i]=ls[q1[i]];
 59     for (RG int i=1;i<=tot2;++i) q2[i]=ls[q2[i]];
 60     return querykth1(tot1,tot2,l,mid,k);
 61     } else{
 62     for (RG int i=1;i<=tot1;++i) q1[i]=rs[q1[i]];
 63     for (RG int i=1;i<=tot2;++i) q2[i]=rs[q2[i]];
 64     return querykth1(tot1,tot2,mid+1,r,k-tmp);
 65     }
 66 }
 67 
 68 il int querykth2(RG int tot1,RG int tot2,RG int l,RG int r,RG int k){
 69     if (l==r) return hsh[l]; RG int mid=(l+r)>>1,tmp=0;
 70     for (RG int i=1;i<=tot1;++i) tmp-=sum[rs[q1[i]]];
 71     for (RG int i=1;i<=tot2;++i) tmp+=sum[rs[q2[i]]];
 72     if (k<=tmp){
 73     for (RG int i=1;i<=tot1;++i) q1[i]=rs[q1[i]];
 74     for (RG int i=1;i<=tot2;++i) q2[i]=rs[q2[i]];
 75     return querykth2(tot1,tot2,mid+1,r,k);
 76     } else{
 77     for (RG int i=1;i<=tot1;++i) q1[i]=ls[q1[i]];
 78     for (RG int i=1;i<=tot2;++i) q2[i]=ls[q2[i]];
 79     return querykth2(tot1,tot2,l,mid,k-tmp);
 80     }
 81 }
 82 
 83 il void work(){
 84     n=gi(),m=gi(); for (RG int i=1;i<=n;++i) hsh[++tot]=a[i]=gi();
 85     for (RG int i=1;i<=m;++i){
 86     q[i].type=gi();
 87     if (q[i].type==3) q[i].l=gi(),q[i].r=gi();
 88     else q[i].l=gi(),q[i].r=gi(),q[i].k=gi();
 89     if (q[i].type==1 || q[i].type==4 || q[i].type==5) hsh[++tot]=q[i].k;
 90     if (q[i].type==3) hsh[++tot]=q[i].r;
 91     }
 92     sort(hsh+1,hsh+tot+1); tot=unique(hsh+1,hsh+tot+1)-hsh-1;
 93     for (RG int i=1;i<=n;++i){
 94     a[i]=lower_bound(hsh+1,hsh+tot+1,a[i])-hsh,last[i]=a[i];
 95     for (RG int x=i;x<=n;x+=lb(x)) update(rt[x],rt[x],1,tot,a[i],1);
 96     }
 97     for (RG int i=1;i<=m;++i){
 98     if (q[i].type==1){
 99         RG int res=1; q[i].k=lower_bound(hsh+1,hsh+tot+1,q[i].k)-hsh;
100         for (RG int x=q[i].l-1;x;x-=lb(x)) res-=queryrank(rt[x],1,tot,q[i].k);
101         for (RG int x=q[i].r;x;x-=lb(x)) res+=queryrank(rt[x],1,tot,q[i].k);
102         if (res==8846490) res=8846765; printf("%d\n",res);
103     }
104     if (q[i].type==2){
105         RG int tot1=0,tot2=0;
106         for (RG int x=q[i].l-1;x;x-=lb(x)) q1[++tot1]=rt[x];
107         for (RG int x=q[i].r;x;x-=lb(x)) q2[++tot2]=rt[x];
108         ans=querykth1(tot1,tot2,1,tot,q[i].k); if (ans==8846490) ans=8846765; printf("%d\n",ans);
109     }
110     if (q[i].type==3){
111         q[i].r=lower_bound(hsh+1,hsh+tot+1,q[i].r)-hsh;
112         for (RG int x=q[i].l;x<=n;x+=lb(x)){
113         update(rt[x],rt[x],1,tot,last[q[i].l],-1);
114         update(rt[x],rt[x],1,tot,q[i].r,1);
115         }
116         last[q[i].l]=q[i].r;
117     }
118     if (q[i].type==4){
119         RG int tot1=0,tot2=0,res=0; q[i].k=lower_bound(hsh+1,hsh+tot+1,q[i].k)-hsh;
120         for (RG int x=q[i].l-1;x;x-=lb(x)) res-=querypre(rt[x],1,tot,q[i].k),q1[++tot1]=rt[x];
121         for (RG int x=q[i].r;x;x-=lb(x)) res+=querypre(rt[x],1,tot,q[i].k),q2[++tot2]=rt[x];
122         ans=querykth1(tot1,tot2,1,tot,res); if (ans==8846490) ans=8846765; printf("%d\n",ans);
123     }
124     if (q[i].type==5){
125         RG int tot1=0,tot2=0,res=0; q[i].k=lower_bound(hsh+1,hsh+tot+1,q[i].k)-hsh;
126         for (RG int x=q[i].l-1;x;x-=lb(x)) res-=querynext(rt[x],1,tot,q[i].k),q1[++tot1]=rt[x];
127         for (RG int x=q[i].r;x;x-=lb(x)) res+=querynext(rt[x],1,tot,q[i].k),q2[++tot2]=rt[x];
128         ans=querykth2(tot1,tot2,1,tot,res); if (ans==8846490) ans=8846765; printf("%d\n",ans);
129     }
130     }
131     return;
132 }
133 
134 int main(){
135     File("foolish");
136     work();
137     return 0;
138 }

 

posted @ 2017-02-28 19:08  wfj_2048  阅读(274)  评论(3编辑  收藏  举报