题目
题解
区间修改,询问区间小于c的个数。分块排序,用vector。至于那个块的大小,好像要用到均值不等式
我不太会。。。就开始一个个试,发现siz=sqrt(n)/4时最快!!!明天去学一下算分块复杂度的方法。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN = 50005;
const int N = 1005;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
vector<int> b[N];
int n,siz;
int a[MAXN],l[N],r[N];
int num,bl[MAXN],inc[MAXN];
inline void reset(int id){
b[id].clear();
for(register int i=l[id];i<=r[id];i++) b[id].push_back(a[i]);
sort(b[id].begin(),b[id].end());
}
inline void build(){
siz=sqrt(n);
siz/log2(n);
num=n/siz;
if(n%siz) num++;
for(register int i=1;i<=n;i++)
bl[i]=(i-1)/siz+1;
for(register int i=1;i<=num;i++){
l[i]=(i-1)*siz+1;
r[i]=i*siz;
}
r[num]=n;
for(register int i=1;i<=num;i++) reset(i);
}
inline void update(int ql,int qr,int w){
if(bl[ql]==bl[qr]){
for(register int i=ql;i<=qr;i++)
a[i]+=w;
reset(bl[ql]);
return;
}
for(register int i=ql;i<=r[bl[ql]];i++)
a[i]+=w;
reset(bl[ql]);
for(register int i=bl[ql]+1;i<bl[qr];i++)
inc[i]+=w;
for(register int i=l[bl[qr]];i<=qr;i++)
a[i]+=w;
reset(bl[qr]);
}
inline int query(int ql,int qr,int c){
int ret=0;
if(bl[ql]==bl[qr]){
for(register int i=ql;i<=qr;i++)
ret+=(a[i]+inc[bl[i]]<c);
return ret;
}
for(register int i=ql;i<=r[bl[ql]];i++)
ret+=(a[i]+inc[bl[i]]<c);
for(register int i=l[bl[qr]];i<=qr;i++)
ret+=(a[i]+inc[bl[i]]<c);
for(register int i=bl[ql]+1;i<bl[qr];i++){
int tar=c-inc[i];
ret+=lower_bound(b[i].begin(),b[i].end(),tar)-b[i].begin();
}
return ret;
}
int main(){
n=rd();
for(register int i=1;i<=n;i++) a[i]=rd();
build();
for(register int i=1;i<=n;i++){
int op,L,R,k;
op=rd();L=rd();R=rd();k=rd();
if(op==0)
update(L,R,k);
else
printf("%d
",query(L,R,k*k));
}
return 0;
}