【bzoj3343 教主的魔法】
Description
教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
Input
第1行为两个整数N、Q。Q为问题数与教主的施法数总和。
第2行有N个正整数,第i个数代表第i个英雄的身高。
第3到第Q+2行每行有一个操作:
若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。
若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。
Output
对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。
Sample Input
5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4
Sample Output
2
3
题解:
分块。对每个块中排序,于是询问就可以二分了。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 int n,Q,m,blo; 9 int a[1000005],b[1000005],bl[1000005],add[1000005]; 10 inline void init(int x){ 11 int L=blo*(x-1)+1,R=min(blo*x,n); 12 for(int i=L;i<=R;i++){ 13 b[i]=a[i]; 14 } 15 sort(b+L,b+R+1); 16 } 17 inline int find(int x,int v){ 18 return min(n,blo*x)+1-(lower_bound(b+(x-1)*blo+1,b+min(n,blo*x)+1,v)-b); 19 } 20 inline int query(int l,int r,int v){ 21 int sum=0; 22 if(bl[l]==bl[r]){ 23 for(int i=l;l<=r;i++){ 24 if(a[i]+add[bl[i]]>=v) sum++; 25 } 26 } 27 else{ 28 for(int i=l;i<=bl[l]*blo;i++) 29 if(a[i]+add[bl[i]]>=v) sum++; 30 for(int i=(bl[r]-1)*blo+1;i<=r;i++) 31 if(a[i]+add[bl[i]]>=v) sum++; 32 } 33 for(int i=bl[l]+1;i<=bl[r]-1;i++) 34 sum+=find(i,v-add[i]); 35 return sum; 36 } 37 inline void update(int l,int r,int v){ 38 if(bl[l]==bl[r]){ 39 for(int i=l;i<=r;i++) 40 a[i]+=v; 41 } 42 else{ 43 for(int i=l;i<=bl[l]*blo;i++) a[i]+=v; 44 for(int i=(bl[r]-1)*blo+1;i<=r;i++) a[i]+=v; 45 } 46 init(bl[l]);init(bl[r]); 47 for(int i=bl[l]+1;i<=bl[r]-1;i++) add[i]+=v; 48 } 49 int main(){ 50 char ch[5]; 51 int x,y,v; 52 scanf("%d%d",&n,&Q); 53 blo=(int)sqrt(n); 54 for(int i=1;i<=n;i++){ 55 scanf("%d",&a[i]); 56 bl[i]=(i-1)/blo+1; 57 } 58 if(n%blo==0) m=n/blo; 59 else m=n/blo+1; 60 for(int i=1;i<=m;i++) init(i); 61 while(Q--){ 62 scanf("%s%d%d%d",ch,&x,&y,&v); 63 if(ch[0]=='M') update(x,y,v); 64 else printf("%d\n",query(x,y,v)); 65 } 66 return 0; 67 }