传送门
正儿八经的分块题。
整个块打add标记,其余的暴力加。
询问的时候整个块sort之后二分找,其余的暴力找。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
const int max_n=1e6+5;
const int max_t=1e4+5;
int n,q,t1,t2,l,r,w,c;
int h[max_n],hh[max_n];
int last[max_t],num[max_n],add[max_t];
inline void Change(int l,int r,int w){
int lrange,rrange;
if (num[l]==num[r]){
for (int i=l;i<=r;++i)
h[i]+=w;
for (int i=last[num[l]-1]+1;i<=last[num[l]];++i)
hh[i]=h[i];
sort(hh+last[num[l]-1]+1,hh+last[num[l]]+1);
return;
}
if (l!=last[num[l]-1]+1){
lrange=num[l]+1;
for (int i=l;i<=last[num[l]];++i)
h[i]+=w;
for (int i=last[num[l]-1]+1;i<=last[num[l]];++i)
hh[i]=h[i];
sort(hh+last[num[l]-1]+1,hh+last[num[l]]+1);
}
else lrange=num[l];
if (r!=last[num[r]]){
rrange=num[r]-1;
for (int i=last[num[r]-1]+1;i<=r;++i)
h[i]+=w;
for (int i=last[num[r]-1]+1;i<=last[num[r]];++i)
hh[i]=h[i];
sort(hh+last[num[r]-1]+1,hh+last[num[r]]+1);
}
else rrange=num[r];
for (int i=lrange;i<=rrange;++i)
add[i]+=w;
}
inline void Query(int l,int r,int c){
int ans=0;
int lrange,rrange;
if (num[l]==num[r]){
for (int i=l;i<=r;++i)
if (h[i]>=c-add[num[l]]) ans++;
printf("%d\n",ans);
return;
}
if (l!=last[num[l]-1]+1){
lrange=num[l]+1;
for (int i=l;i<=last[num[l]];++i)
if (h[i]>=c-add[num[l]]) ans++;
}
else lrange=num[l];
if (r!=last[num[r]]){
rrange=num[r]-1;
for (int i=last[num[r]-1]+1;i<=r;++i)
if (h[i]>=c-add[num[r]]) ans++;
}
else rrange=num[r];
for (int i=lrange;i<=rrange;++i){
if (hh[last[i]]<c-add[i]) continue;
if (hh[last[i-1]+1]>=c-add[i]){
ans+=last[i]-(last[i-1]+1)+1;
continue;
}
int loc=lower_bound(hh+last[i-1]+1,hh+last[i]+1,c-add[i])-hh;
if (hh[loc]<c-add[i]) ++loc;
ans+=last[i]-loc+1;
}
printf("%d\n",ans);
}
int main(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;++i){
scanf("%d",&h[i]);
hh[i]=h[i];
}
t1=(int)sqrt(n);
if (n%t1==0) t2=n/t1;
else t2=n/t1+1;
for (int i=1;i<=n;++i)
if (i%t1==0)
num[i]=i/t1;
else
num[i]=i/t1+1;
for (int i=1;i<=t2;++i)
last[i]=min(i*t1,n);
for (int i=1;i<=t2;++i)
sort(hh+last[i-1]+1,hh+last[i]+1);
for (int i=1;i<=q;++i){
char ch=getchar();
while (ch!='M'&&ch!='A') ch=getchar();
if (ch=='M'){
scanf("%d%d%d",&l,&r,&w);
if (l>r) swap(l,r);
Change(l,r,w);
}
else{
scanf("%d%d%d",&l,&r,&c);
if (l>r) swap(l,r);
Query(l,r,c);
}
}
}
分块的细节问题一定要注意。