教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
分块模板题。
整块直接打标记,散块暴力加。开个数组维护单调性。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
int n,q,a[MAXN],bl[MAXN],blc,b[MAXN];
int tag[MAXN];
inline void reset(int block){
int l=(block-1)*blc+1,r=min(block*blc,n);
for(int i=l;i<=r;i++)
b[i]=a[i];
sort(b+l,b+1+r);
}
inline void bladd(int l,int r,int w){
for(int i=l;i<=min(bl[l]*blc,r);i++)
a[i]+=w;
reset(bl[l]);//sort(a+(bl[l]-1)*blc+1,min(a+1+n,a+1+bl[l]*blc));
if(bl[l]!=bl[r]){
for(int i=(bl[r]-1)*blc+1;i<=r;i++)
a[i]+=w;
reset(bl[r]);//sort(a+(bl[r]-1)*blc+1,min(a+1+n,a+1+bl[r]*blc));
}
for(int i=bl[l]+1;i<=bl[r]-1;i++)tag[i]+=w;
}
inline int find(int block,int c){
int l=(block-1)*blc+1,r=min(block*blc,n);
int R=r;
while(l<=r){
int mid=l+r>>1;
if(b[mid]<c)l=mid+1;
else r=mid-1;
}
return R-l+1;
}
inline int querymore(int l,int r,int c){
int ans=0;
for(int i=l;i<=min(r,bl[l]*blc);i++){
if(a[i]+tag[bl[l]]>=c)ans++;
}
if(bl[l]!=bl[r]){
for(int i=(bl[r]-1)*blc+1;i<=r;i++){
if(a[i]+tag[bl[r]]>=c)ans++;
}
}
for(int i=bl[l]+1;i<=bl[r]-1;i++){
ans+=find(i,c-tag[i]);
}
return ans;
}
int main(){
int l,r,w,c;
scanf("%d%d",&n,&q);
blc=sqrt(n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
bl[i]=(i-1)/blc+1;
}
for(int i=1;i<=n;i+=blc)
sort(b+i,min(b+1+n,b+i+blc));
char tem;
//for(int i=1;i<=n;i++)cout<<a[i]<<" ";
for(int i=1;i<=q;i++){
cin>>tem;
if(tem=='M'){
scanf("%d%d%d",&l,&r,&w);
bladd(l,r,w);
}
else {
scanf("%d%d%d",&l,&r,&c);
printf("%d\n",querymore(l,r,c));
}
}
return 0;
}