题解:P13977 数列分块入门 2
P13977
主要讲一下代码细节,对于数据结构的原理请去看模板。
Solution
首先有两种操作,区间查询和区间加法,先说说加法。
首先判断
接下来是区间查询有多少个小于等于
具体实现细节请看代码,个人认为应该容易看懂。
Code
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
LL n,a[500005],lazy[500005],len,L[500005];
vector<LL> v[50005];
inline LL get(LL x){
return x/len+1;
}
void resort(LL x){
int i=L[x];v[x].clear();
while(get(i)==x&&i<=n) v[x].push_back(a[i++]);
sort(v[x].begin(),v[x].end());
}
void update(LL l,LL r,LL c){
if(get(l)==get(r)){
for(int i=l;i<=r;i++) a[i]+=c;
resort(get(l));
}else {
int i=l,j=r;
while (get(i) == get(l)) a[i++] += c;
while (get(j) == get(r)) a[j--] += c;
resort(get(l));resort(get(r));
for (int k = get(i);k <= get(j);k++) lazy[k] += c;
}
}
LL query(LL l,LL r,LL c){
LL res=0;
if(get(l)==get(r)){
for(int i=l;i<=r;i++){
if(a[i]+lazy[get(i)]<c) res++;
}
}
else{
int i=l,j=r;
while(get(i)==get(l)) if(a[i++]+lazy[get(l)]<c) res++;
while(get(j)==get(r)) if(a[j--]+lazy[get(r)]<c) res++;
for (int k = get(i);k <= get(j);k++) {
res += lower_bound(v[k].begin(), v[k].end(), c - lazy[k]) - v[k].begin();
}
}
return res;
}
int main(){
cin>>n;
len=int(sqrt(n));
memset(L,0x3f,sizeof(L));
for(LL i=1;i<=n;i++){
cin>>a[i];
LL x=get(i);
L[x]=min(L[x],i);
v[x].push_back(a[i]);
}
for(int i=1;i<=n/len;i++) sort(v[i].begin(),v[i].end());
for(int i=1;i<=n;i++){
LL l,r,c,op;
cin>>op>>l>>r>>c;
if(op) cout<<query(l,r,c*c)<<endl;
else{
update(l,r,c);
}
}
return 0;
}