[BZOJ2388] 旅游计划 题解
两个操作相当于区间加等差数列和求区间最大值,过于复杂,考虑分块。
对于每个块,我们记录 \(ad_j\) 表示这个块内每个位置共同的增量,记录 \(cd_j\) 表示这个块内整体加上的等差数列的公差。我们可以通过将部分等差数列的值转移到 \(ad_j\) 中去,这样每个位置的值就是:
\[ans_i=(i-fs_j+1)\times cd_j+a_i+ad_j
\]
我们将 \(cd_j\) 看作 \(x\),就会获得一大堆的一次函数。由于 \(cd_j\) 会变化,考虑使用凸包进行维护。
那么我们可以在每个块内维护一个下凸包,查询的时候直接二分即可。
时间复杂度 \(O(n\sqrt n\log n)\)。
#include<bits/stdc++.h>
#define int long long
#define idx(x) ((x-1)/kl+1)
#define fs(x) ((x-1)*kl+1)
#define ed(x) min((x)*kl,n)
#define as(x,id) ((x-fs(id)+1)*cd[id]+a[x]+ad[id])
using namespace std;
const int N=1e5+5,M=325;
int n,kl,a[N],st[M][M];
int m,ad[M],cd[M],tp[M];
int check(int i,int j,int k){
return (a[j]-a[i])*(i-k)>(a[k]-a[i])*(i-j);
}void build(int x){
while(tp[x]) st[x][tp[x]--]=0;
for(int i=fs(x);i<=ed(x);st[x][++tp[x]]=i++)
while(tp[x]>1&&check(st[x][tp[x]-1],st[x][tp[x]],i)) tp[x]--;
}int maxn(int x){
int l=2,r=tp[x],ans=st[x][1];
while(l<=r){
int mid=(l+r)/2,ca=st[x][mid-1],cb=st[x][mid];
if(a[ca]+ca*cd[x]>a[cb]+cb*cd[x]) r=mid-1;
else ans=st[x][mid],l=mid+1;
}return as(ans,x);
}void add(int l,int r,int gd){
int j=1;if(idx(l)==idx(r)){
for(int i=l;i<r;i++,j++) a[i]+=j*gd;
for(int i=r;i<=ed(idx(l));i++) a[i]+=j*gd;
for(int i=idx(l)+1;ed(i-1)<n;i++) ad[i]+=j*gd;
return build(idx(l));
}for(int i=l;i<=ed(idx(l));i++,j++) a[i]+=j*gd;
for(int i=idx(l)+1;i<idx(r);i++,j+=kl) ad[i]+=j*gd-gd,cd[i]+=gd;
for(int i=fs(idx(r));i<r;i++,j++) a[i]+=j*gd;
for(int i=r;i<=ed(idx(r));i++) a[i]+=j*gd;
for(int i=idx(r)+1;ed(i-1)<n;i++) ad[i]+=j*gd;
return build(idx(l)),build(idx(r));
}int answ(int l,int r){
int mx=-1e18;
if(idx(l)<idx(r)){
for(int i=l;i<=ed(idx(l));i++) mx=max(mx,as(i,idx(l)));
for(int i=fs(idx(r));i<=r;i++) mx=max(mx,as(i,idx(r)));
for(int i=idx(l)+1;i<idx(r);i++) mx=max(mx,maxn(i));
}else for(int i=l;i<=r;i++) mx=max(mx,as(i,idx(l)));
return mx;
}signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n,kl=min(n,320ll);
for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
for(int i=1;ed(i-1)<n;i++) build(i);
cin>>m;while(m--){
int opt,l,r,k;cin>>opt>>l>>r;
if(opt) cout<<answ(l,r)<<"\n";
else cin>>k,add(l,r,k);
}return 0;
}

浙公网安备 33010602011771号