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。
正经的分块题啊。。
分块后对每次修改,若l r 覆盖该块则直接加lazy
不覆盖则暴力修改后排序
查询类似 若不覆盖则暴力
覆盖则二分
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Forr(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
const int N=1000000+5;
inline int read(){
char c=getchar();
while(c<'0'||c>'9')c=getchar();
int x=c-'0';
c=getchar();
while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
return x;
}
int compare(const int w1,const int w2){
return w1>w2;
}
int n,m;
int a[N],b[N],block,belong[N],cnt,l[N],r[N],lazy[N];
char s[10];
int check(int w,int z){
int le=l[w],ri=r[w];
while(le<ri){
int mid=(le+ri)/2;
if(lazy[w]+a[mid]<z)ri=mid;
else le=mid+1;
}
if(lazy[w]+a[le]>=z)le++;
return le-l[w];
}
void reset(int nowb){
For(i,l[nowb],r[nowb])a[i]=b[i];
sort(a+l[nowb],a+r[nowb]+1,compare);
}
void add(int x,int y,int z){
int nowb=belong[x];
if(l[nowb]<x||r[nowb]>y){
For(i,max(l[nowb],x),min(r[nowb],y))b[i]+=z;
reset(nowb);
nowb++;
}
while(nowb<=cnt&&x<=l[nowb]&&y>=r[nowb]){
lazy[nowb]+=z;
nowb++;
}
if(nowb==cnt+1)return;
if(y>=l[nowb]){
For(i,max(l[nowb],x),min(r[nowb],y))b[i]+=z;
reset(nowb);
}
return;
}
int ans;
void query(int x,int y,int z){
ans=0;
int nowb=belong[x];
if(l[nowb]<x||r[nowb]>y){
For(i,max(l[nowb],x),min(r[nowb],y))
if(b[i]+lazy[nowb]>=z)ans++;
nowb++;
}
while(nowb<=cnt&&x<=l[nowb]&&y>=r[nowb]){
ans+=check(nowb,z);
nowb++;
}
if(y>=l[nowb]&&nowb!=cnt+1){
For(i,max(l[nowb],x),min(r[nowb],y))
if(b[i]+lazy[nowb]>=z)ans++;
}
cout<<ans<<endl;
return;
}
int main(){
freopen("a.in","r",stdin);
n=read();m=read();
For(i,1,n){a[i]=read();b[i]=a[i];}
block=int(sqrt(n));
if(n%block)cnt=n/block+1;
else cnt=n/block;
For(i,1,n)belong[i]=(i-1)/block+1;
For(i,1,cnt){l[i]=(i-1)*block+1;r[i]=i*block;}
r[cnt]=n;
For(i,1,cnt)sort(a+l[i],a+r[i]+1,compare);
int x,y,z;
For(i,1,m){
scanf("%s",s);
x=read();y=read();z=read();
if(s[0]=='M')add(x,y,z);
if(s[0]=='A')query(x,y,z);
}
return 0;
}