3343: 教主的魔法
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 821 Solved: 364
[Submit][Status][Discuss]
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行每行有一个操作:
(1) 若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。
(2) 若第一个字母为“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
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4
Sample Output
2
3
3
HINT
【输入输出样例说明】
原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。
【数据范围】
对30%的数据,N≤1000,Q≤1000。
对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000。
Source
代码:
View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 1000010 4 int N,a[MAXN],h[MAXN],pos[MAXN],add[1010],block; 5 int read() 6 { 7 int s=0,fh=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 10 return s*fh; 11 } 12 void cl(int k) 13 { 14 int l=(k-1)*block+1,r=min(k*block,N),i; 15 for(i=l;i<=r;i++)a[i]=h[i]; 16 sort(a+l,a+r+1); 17 } 18 void Add(int l,int r,int c) 19 { 20 int i; 21 if(pos[l]==pos[r]) 22 { 23 for(i=l;i<=r;i++)h[i]+=c; 24 cl(pos[l]); 25 } 26 else 27 { 28 for(i=l;i<=pos[l]*block;i++)h[i]+=c; 29 for(i=(pos[r]-1)*block+1;i<=r;i++)h[i]+=c; 30 for(i=pos[l]+1;i<=pos[r]-1;i++)add[i]+=c; 31 cl(pos[l]);cl(pos[r]); 32 } 33 } 34 int Find(int k,int c) 35 { 36 int l=(k-1)*block+1,r=min(k*block,N),t=0,mid; 37 while(l<=r) 38 { 39 mid=(l+r)/2; 40 if(a[mid]<c)l=mid+1; 41 else t=mid,r=mid-1; 42 } 43 if(t==0)return 0; 44 return min(k*block,N)-t+1; 45 } 46 int Query(int l,int r,int c) 47 { 48 int ans=0,i; 49 if(pos[l]==pos[r]) 50 { 51 for(i=l;i<=r;i++)if(h[i]+add[pos[i]]>=c)ans++; 52 } 53 else 54 { 55 for(i=l;i<=pos[l]*block;i++)if(h[i]+add[pos[i]]>=c)ans++; 56 for(i=(pos[r]-1)*block+1;i<=r;i++)if(h[i]+add[pos[i]]>=c)ans++; 57 for(i=pos[l]+1;i<=pos[r]-1;i++)ans+=Find(i,c-add[i]); 58 } 59 return ans; 60 } 61 int main() 62 { 63 int Q,i,m,L,R,W; 64 char fh[2]; 65 N=read();Q=read(); 66 block=(int)sqrt(N); 67 for(i=1;i<=N;i++) 68 { 69 h[i]=read(); 70 pos[i]=(i-1)/block+1; 71 } 72 if(N==block*block)m=block; 73 else m=block+1; 74 for(i=1;i<=m;i++)cl(i); 75 for(i=1;i<=Q;i++) 76 { 77 scanf(" %s",fh);L=read();R=read();W=read(); 78 if(fh[0]=='M')Add(L,R,W); 79 else printf("%d ",Query(L,R,W)); 80 } 81 return 0; 82 }