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
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
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 }