斜率优化DP
令
S[i]=∑ij=1x[i]
易得出转移方程
f[i]=max(f[j]+a(S[i]−S[j])2+b(S[i]−S[j])+c)
考虑斜率优化
设
x<y
且x优于y
f[x]+a(S[i]−S[x])2+b(S[i]−S[x])+c>f[y]+a(S[i]−S[y])2+b(S[i]−S[y])+c
f[x]+a(S[i]2−2S[i]S[x]+S[x]2)+bS[i]−bS[x]>f[y]+a(S[i]2−2S[i]S[y]+S[y]2)+bS[i]−bS[y]
f[x]−2aS[i]S[x]+aS[x]2−bS[x]>f[y]−2aS[i]S[y]+aS[y]2−bS[y]
f[x]−f[y]+aS[x]2−bS[x]−aS[y]2+bS[y]>2aS[i](S[x]−S[y])
f[x]−f[y]+a(S[x]2−S[y]2)−b(S[x]−S[y])2a(S[x]−S[y])>S[i]
然后就好了
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1000000
using namespace std;
typedef long long LL;
int n,r,w,que[MAXN+5];
LL f[MAXN+5],a,b,c,s[MAXN+5];
inline char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
inline LL _read(){
LL num=0,flag=1; char ch=readc();
while (!isdigit(ch)&&ch!='-') ch=readc();
if (ch=='-') flag=-1,ch=readc();
while (isdigit(ch)) { num=num*10+ch-48; ch=readc(); }
return num*flag;
}
#define sqr(x) ((x)*(x))
inline LL K(int x,int y){
return (f[x]-f[y]+a*(sqr(s[x])-sqr(s[y]))-b*(s[x]-s[y]))/(2*a*(s[x]-s[y]));
}
int main(){
n=_read();
a=_read(),b=_read(),c=_read();
for (int i=1;i<=n;i++)
s[i]=_read(),s[i]+=s[i-1],f[i]=1e18;
for (int i=1;i<=n;i++){
while (r<w&&K(que[r],que[r+1])<s[i]) r++;
f[i]=f[que[r]]+a*sqr(s[i]-s[que[r]])+b*(s[i]-s[que[r]])+c;
while (r<w&&K(que[w-1],que[w])>=K(que[w],i)) w--;
que[++w]=i;
}
return printf("%lld\n",f[n]),0;
}