题意
OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 n n n 个最著名的经典连接起来,让游客可以通过火车从铁路起点( 1 1 1 号景点)出发,依次游览每个景区。为了更好的评价这条铁路,xkszltl 为每一个景区都赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。
xkszltl 希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而 xkszltl 的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,xkszltl 无法及时完成任务,于是找到了准备虐杀 NOI2019 的你,希望你能帮助他完成这个艰巨的任务。
题解
考虑分块凸包
设
s
i
s_i
si 表示i的前缀和,
d
j
d_j
dj 表示
j
j
j 这个区间的每个数都加上它,
f
j
f_j
fj 表示每位置的前缀和都加上它
对于第
j
j
j 块的区间
[
l
,
r
]
[l,r]
[l,r] 考虑它的
a
n
s
ans
ans
a
n
s
=
m
a
x
i
=
l
r
f
j
+
d
j
×
(
i
−
l
)
+
s
i
ans=max_{i=l}^{r} f_j+d_j \times (i-l)+s_i
ans=maxi=lrfj+dj×(i−l)+si
设
x
=
i
−
l
x=i-l
x=i−l ,
y
=
s
i
y=s_i
y=si ,把式子化简成
y
=
−
d
j
×
x
+
a
n
s
−
f
j
y=-d_j \times x+ans-f_j
y=−dj×x+ans−fj 故维护上凸壳即可
#include <bits/stdc++.h>
#define I inline
#define db double
#define LL long long
using namespace std;
const int N=1e5+5,M=350;
LL s[N],f[M],d[M],c[M];
int m,n,B,b[N],L[M],R[M],Z,S[M],p[M][M],sz[M];
I db K(int x,int y){return (db)(s[y]-s[x])/(db)(y-x);}
I void U(int x){
int t=0;S[++t]=L[x];
for (int i=L[x]+1;i<=R[x];i++){
while(t>1 && K(S[t-1],S[t])<K(S[t-1],i))
t--;
S[++t]=i;
}
sz[x]=t;p[x][t+1]=n+1;
for (int i=1;i<=t;i++) p[x][i]=S[i];
}
I void D(int x){
LL t=f[x];
for (int i=L[x];i<=R[x];i++)
s[i]+=t+c[x],t+=d[x];
f[x]=c[x]=d[x]=0;
}
I void C(int l,int r,LL k){
int x=b[l],y=b[r];LL t=k*(L[x+1]-l+1);
for (int i=x+1;i<y;i++)
f[i]+=t,d[i]+=k,t+=k*(R[i]-L[i]+1);
D(x);t=k;
for (int i=l;i<=R[x] && i<=r;i++)
s[i]+=t,t+=k;
U(x);D(y);if (x!=y){
t=k*(L[y]-l+1);
for (int i=L[y];i<=r;i++)
s[i]+=t,t+=k;
}t=k*(r-l+1);
for (int i=r+1;i<=R[y];i++) s[i]+=t;
U(y);for (int i=y+1;i<=Z;i++) c[i]+=t;
}
I LL G(int x){
if (!x || x>n) return (LL)-2e18;
int y=b[x];return s[x]+c[y]+f[y]+d[y]*(x-L[y]);
}
I LL A(int x){
int l=1,r=sz[x];
while(l<=r){
int mid=(l+r)>>1;
LL t1=G(p[x][mid-1]);
LL t2=G(p[x][mid]);
LL t3=G(p[x][mid+1]);
if (t1<t2 && t2<t3) l=mid+1;
else if (t1>t2 && t2>t3) r=mid-1;
else return t2;
}
}
I LL Q(int l,int r){
int x=b[l],y=b[r];LL t=-2e18;
for (int i=x+1;i<y;i++)
t=max(A(i),t);
for (int i=l;i<=R[x] && i<=r;i++)
t=max(G(i),t);if (x!=y)
for (int i=L[y];i<=r;i++)
t=max(G(i),t);return t;
}
int main(){
scanf("%d",&n);B=sqrt(n);
for (int x,i=1;i<=n;i++){
scanf("%d",&x);
s[i]=s[i-1]+x;
b[i]=(i-1)/B+1;
if (b[i]!=b[i-1])
L[b[i]]=i,R[b[i-1]]=i-1;
}R[Z=b[n]]=n;
for (int i=1;i<=Z;i++) U(i);
scanf("%d",&m);LL x;
for (int op,l,r;m--;){
scanf("%d%d%d",&op,&l,&r);
if (!op) scanf("%lld",&x),C(l,r,x);
else printf("%lld\n",Q(l,r));
}
return 0;
}