【题解】CF631E Product Sum
\(\text{Solution:}\)
考虑转化操作,显然有,设从 \(i\) 转移到 \(j,\) 若 \(i>j\) 贡献则为 \(s_{i-1}-s_{j}-(i-j)\times a_i,s_i=\sum_{i=1}^n a_i\)
如果 \(i<j\) 则贡献为 \((j-i)\times a_i-(s_j-s_i)\)
这东西拆出来发现就是斜率优化。直接李超树维护即可 \(O(n\log n),\) 注意要正反来两遍。
顺便学习一下很短的李超树写法,每次令当前点是中点处值小的直线,则斜率小就往左边走,否则往右边走。代码就很短了。
注意需要特判边界,代码里面是动态开点,走到不存在的点应当返回 $-\infty $
简洁版本代码:
#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1LL << 60);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
if(x==0){*O++='0';return;}
if(x<0)*O++='-',x=-x;ptop=0;
while(x)pst[++ptop]=x%10,x/=10;
while(ptop)*O++=pst[ptop--]+'0';
if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
return s * w;
}
inline void write(int x) {
if (x < 0)putchar('-'), x = -x;
if (x > 9)write(x / 10);
pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
int res = 1;
while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N = 2e5 + 10;
namespace Refined_heart{
int n,sum[N],a[N];
namespace LiChao{
const int M=7e6+10;
struct Node{
int k,b;
inline int calc(int x){return k*x+b;}
}tr[M];
int node,rt,ls[M],rs[M];
inline int CL(int k,int b,int x){return k*x+b;}
void insert(int &x,int l,int r,int k,int b){
if(!x)x=++node;
int mid=(l+r)>>1;
int now=tr[x].calc(mid);
int cg=CL(k,b,mid);
if(!tr[x].k){
tr[x].k=k;tr[x].b=b;
return;
}
if(cg>now){
int kk=tr[x].k,bb=tr[x].b;
tr[x].k=k;tr[x].b=b;b=bb;k=kk;
}
if(l!=r){
if(k<tr[x].k)insert(ls[x],l,mid,k,b);
else insert(rs[x],mid+1,r,k,b);
}
}
int query(int x,int l,int r,int v){
if(!x)return -inf;
int ans=tr[x].calc(v);
if(l==r)return ans;
int mid=(l+r)>>1;
ans=Max(ans,v<=mid?query(ls[x],l,mid,v):query(rs[x],mid+1,r,v));
return ans;
}
}
using namespace LiChao;
int f[N],g[N];
void solve(){
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)sum[i]=sum[i-1]+a[i];
int ans=0;
for(int i=1;i<=n;++i)ans+=i*a[i];
int v=-inf;
for(int i=1;i<=n;++i){
f[i]=query(rt,-1000001,1000001,a[i])+sum[i-1]-i*a[i];
insert(rt,-1000001,1000001,i,-sum[i-1]);
}
for(int i=0;i<=n;++i)cmax(v,ans+f[i]);
for(int i=0;i<=node;++i)tr[i]=(Node){0,0},ls[i]=0,rs[i]=0;
node=0;rt=0;
for(int i=n;i>=1;--i){
g[i]=query(rt,-1000001,1000001,a[i])+sum[i]-i*a[i];
insert(rt,-1000001,1000001,i,-sum[i]);
}
for(int i=0;i<=n;++i)cmax(v,ans+g[i]);
write(v);pc('\n');
}
}
signed main(){
freopen("in.txt","r",stdin);
Refined_heart::solve();
return 0;
}