其实我们只需要将每个块有序的存起来,在查询比 小的数的数量时,只需要散块暴力遍历,整块 lower_bound 即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e4+7;
int a[N],b[N],s[N],id[N],n,len;
int blk[507][507],siz[507];
void sorted(int bid){
int l=(bid-1)*len+1;
int r=min(bid*len,n);
int j=0;
for(int i=l;i<=r;i++)blk[bid][++j]=a[i];
siz[bid]=j;
sort(blk[bid]+1,blk[bid]+siz[bid]+1);
}
void add(int l,int r,int x){
if(id[l]==id[r]){
for(int i=l;i<=r;i++)a[i]+=x,s[id[l]]+=x;
sorted(id[l]);
return;
}
for(int i=l;id[i]==id[l];i++)a[i]+=x,s[id[l]]+=x;
sorted(id[l]);
for(int i=id[l]+1;i<id[r];i++)b[i]+=x,s[i]+=len*x;
for(int i=r;id[r]==id[i];i--)a[i]+=x,s[id[r]]+=x;
sorted(id[r]);
}
int query(int l,int r,int c){
int ans=0;
if(id[l]==id[r]){
for(int i=l;i<=r;i++){
if(a[i]+b[id[l]]<c*c*1ll)ans++;
}
return ans;
}
for(int i=l;id[i]==id[l];i++)if(a[i]+b[id[i]]<c*c*1ll)ans++;
for(int i=id[l]+1;i<id[r];i++){
int l=c*c*1ll-b[i];
int x=lower_bound(blk[i]+1,blk[i]+1+siz[i],l)-blk[i]-1;
ans+=x;
}
for(int i=r;id[i]==id[r];i--)if(a[i]+b[id[i]]<c*c*1ll)ans++;
return ans;
}
signed main(){
cin>>n;
len=sqrt(n);
int cnt=(n+len-1)/len;
for(int i=1;i<=n;i++){
cin>>a[i];
id[i]=(i-1)/len+1;
s[id[i]]+=a[i];
}
for(int i=1;i<=cnt;i++)sorted(i);
for(int i=1;i<=n;i++){
int opt,l,r,c;
cin>>opt>>l>>r>>c;
if(opt==0)add(l,r,c);
else cout<<query(l,r,c)<<endl;
}
}
暂无评论