今天学了一下分块,维护中间的块,然后两边的零散的暴力一下.
分块的板子题,主要简单维护一下中间的块
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,q;
int block,cnt;
int belong[N],val[N],mark[(N>>2)+10];
vector<int>kuai[(N>>2)+10];
void init(){
for(int i=1;i<=cnt;i++){
sort(kuai[i].begin(),kuai[i].end());
}
}
void update(int u){
kuai[u].clear();
for(int i=(u-1)*block+1;i<=u*block;++i)
kuai[u].push_back(val[i]);
sort(kuai[u].begin(),kuai[u].end());
}
void add(int l,int r,int x){
for(int i=l;i<=min(r,belong[l]*block);++i)
val[i]+=x;
update(belong[l]);
if(belong[l]!=belong[r]){
for(int i=belong[l]+1;i<belong[r];++i)
mark[i]+=x;
for(int i=(belong[r]-1)*block+1;i<=r;++i)
val[i]+=x;
update(belong[r]);
}
}
int search(int l,int r,int x){
int num(0);
for(int i=l;i<=min(r,belong[l]*block);++i)
if(val[i]+mark[belong[i]]>=x)++num;
if(belong[l]!=belong[r]){
for(int i=belong[l]+1;i<belong[r];++i){
int l1=0,r1=block-1;
while(l1<=r1){
int mid=l1+((r1-l1)>>1);
if(kuai[i][mid]+mark[i]<x)l1=mid+1;
else r1=mid-1;
}
num+=block-l1;
}
for(int i=(belong[r]-1)*block+1;i<=r;++i)
if(val[i]+mark[belong[i]]>=x)++num;
}
return num;
}
signed main(){
cin>>n>>q;
block=sqrt(n);
for(int i=1;i<=n;i++){
cin>>val[i];
if(i%block==1)cnt++;
belong[i]=cnt;
kuai[cnt].push_back(val[i]);
}
init();
char op;
while(q--){
int L,R,u;
cin>>op>>L>>R>>u;
if(op=='M'){
add(L,R,u);
}
else{
cout<<search(L,R,u)<<endl;
}
}
return 0;
}
还是太菜了,调了几个小时没调出来qwq,感觉代码细节上有问题,等过几天再写一下qwq
这题给的数据范围很大,所以首先要离散化,然后用前缀和优化,超了,然后题解要用了预处理,
代码就不贴了,下次吧