logo AlgoBeat OnlineJudge
登录 注册

题解

作者: _ZXY_  ·  发布于 2026-05-17 19:45:24  ·  最后修改于 2026-05-17 19:49:29
已通过
审核员:Lightning ING · 2026-05-17 19:49:29

其实我们只需要将每个块有序的存起来,在查询比 小的数的数量时,只需要散块暴力遍历,整块 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;
    }
}

暂无评论

登录 后即可评论。