logo AlgoBeat OnlineJudge
登录 注册

题解

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

我们只需存有序完整块,在查询 的前驱时,散块暴力遍历查找 的前驱,整块 lower_bound,最后将所有候选值取 即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int N=1e5+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=LLONG_MIN;
    if(id[l]==id[r]){
        for(int i=l;i<=r;i++){
            if(a[i]+b[id[l]]<c)ans=max(ans,a[i]+b[id[l]]);
        }
        return ans;
    }
    for(int i=l;id[i]==id[l];i++)if(a[i]+b[id[i]]<c)ans=max(ans,a[i]+b[id[l]]);
    for(int i=id[l]+1;i<id[r];i++){
        int lp=c-b[i];
        int *x=lower_bound(blk[i]+1,blk[i]+1+siz[i],lp);
        if(x!=blk[i]+1){
            int p=*(x-1);
            ans=max(ans,p+b[i]);
        }
    }
    for(int i=r;id[i]==id[r];i--)if(a[i]+b[id[i]]<c)ans=max(ans,a[i]+b[id[r]]);
    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{
            int ans=query(l,r,c);
            if(ans==LLONG_MIN)ans=-1;
            cout<<ans<<endl;
        }
    }
}

暂无评论

登录 后即可评论。