传送门biu~
分块。把每个块内的英雄按高度排序。增加身高的时候,对于完整的块打标记;对于不完整的块直接暴力重构。查询身高的时候,对于完整的块二分答案;对于不完整的块暴力求解。时间复杂度
O(Qn√)
。
#include<bits/stdc++.h>
using namespace std;
int n,T,blocksiz,maxblock;
struct Hero{
int val,block,id;
bool operator<(const Hero&r)const{return val<r.val;}
}a[1000005];
int add_mark[1005];
int main(){
scanf("%d%d",&n,&T);
blocksiz=sqrt(n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i].val);
a[i].id=i;a[i].block=(i-1)/blocksiz+1;
}
maxblock=a[n].block;
for(int i=2;i<=maxblock-1;++i)
sort(a+(i-1)*blocksiz+1,a+i*blocksiz+1);
while(T--){
char opt[3];
int x,y,c;
scanf("%s%d%d%d",opt,&x,&y,&c);
if(opt[0]=='M'){
int L=a[x].block+1;
int R=a[y].block-1;
if(L<=R){
for(int i=L;i<=R;++i) add_mark[i]+=c;
for(int i=(a[x].block-1)*blocksiz+1;i<=a[x].block*blocksiz;++i)
if(x<=a[i].id) a[i].val+=c;
if(a[x].block!=1) sort(a+(a[x].block-1)*blocksiz+1,a+a[x].block*blocksiz+1);
for(int i=(a[y].block-1)*blocksiz+1;i<=a[y].block*blocksiz;++i)
if(a[i].id<=y) a[i].val+=c;
if(a[y].block!=maxblock) sort(a+(a[y].block-1)*blocksiz+1,a+a[y].block*blocksiz+1);
}
else{
for(int i=(a[x].block-1)*blocksiz+1;i<=a[x].block*blocksiz;++i)
if(x<=a[i].id && a[i].id<=y) a[i].val+=c;
if(a[x].block!=1 && a[x].block!=maxblock) sort(a+(a[x].block-1)*blocksiz+1,a+a[x].block*blocksiz+1);
}
}
else{
int L=a[x].block+1;
int R=a[y].block-1;
int ans=0;
if(L<=R){
for(int i=L;i<=R;++i){
Hero tmp;tmp.val=c-add_mark[i];
ans+=a+i*blocksiz+1-lower_bound(a+(i-1)*blocksiz+1,a+i*blocksiz+1,tmp);
}
for(int i=(a[x].block-1)*blocksiz+1;i<=a[x].block*blocksiz;++i) ans+=(x<=a[i].id && a[i].val+add_mark[a[x].block]>=c);
for(int i=(a[y].block-1)*blocksiz+1;i<=min(a[y].block*blocksiz,n);++i) ans+=(a[i].id<=y && a[i].val+add_mark[a[y].block]>=c);
}
else{
for(int i=(a[x].block-1)*blocksiz+1;i<=min(a[x].block*blocksiz,n);++i) ans+=(x<=a[i].id && a[i].id<=y && a[i].val+add_mark[a[x].block]>=c);
}
printf("%d\n",ans);
}
}
return 0;
}