Solution
首先可以得到 d p dp dp 方程 f [ i ] = m a x ( f [ j ] + a ( s u m [ i ] − s u m [ j ] ) 2 + b ( s u m [ i ] − s u m [ j ] ) + c ) f[i]=max(f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c) f[i]=max(f[j]+a(sum[i]−sum[j])2+b(sum[i]−sum[j])+c)
f [ i ] = f [ j ] + a ⋅ s u m [ i ] 2 − 2 a ⋅ s u m [ i ] ⋅ s u m [ j ] + a ⋅ s u m [ j ] 2 + b ⋅ s u m [ i ] − b ⋅ s u m [ j ] + c f[i]=f[j]+a\cdot sum[i]^2-2a\cdot sum[i]\cdot sum[j]+a\cdot sum[j]^2+b\cdot sum[i]-b\cdot sum[j]+c f[i]=f[j]+a⋅sum[i]2−2a⋅sum[i]⋅sum[j]+a⋅sum[j]2+b⋅sum[i]−b⋅sum[j]+c
f [ j ] + a ⋅ s u m [ j ] 2 − b ⋅ s u m [ j ] + c = 2 a ⋅ s u m [ i ] ⋅ s u m [ j ] + f [ i ] + a ⋅ s u m [ i ] 2 − b ⋅ s u m [ i ] f[j]+a\cdot sum[j]^2-b\cdot sum[j]+c=2a\cdot sum[i]\cdot sum[j]+f[i]+a\cdot sum[i]^2-b\cdot sum[i] f[j]+a⋅sum[j]2−b⋅sum[j]+c=2a⋅sum[i]⋅sum[j]+f[i]+a⋅sum[i]2−b⋅sum[i]
然后令点为 ( s u m [ j ] , f [ j ] + a ⋅ s u m [ j ] 2 − b ⋅ s u m [ j ] + c ) (sum[j],f[j]+a\cdot sum[j]^2-b\cdot sum[j]+c) (sum[j],f[j]+a⋅sum[j]2−b⋅sum[j]+c)
注:题目求的是最大值!要维护上凸包!
Code
#include <cstdio>
#define ll long long
#define db double
const int N=1000010;
int n,a,b,c,q[N];
db sum[N],f[N];
inline db X(int i){return sum[i];}
inline db Y(int i){return f[i]+a*sum[i]*sum[i]-b*sum[i]+c;}
inline db slope(int i,int j){return (Y(i)-Y(j))/(X(i)-X(j));}
int main(){
scanf("%d%d%d%d",&n,&a,&b,&c);
for(int i=1;i<=n;i++) {
scanf("%lf",&sum[i]);
sum[i]+=sum[i-1];
}
int h=1,t=1;
for(int i=1;i<=n;i++){
while(h<t && slope(q[h],q[h+1])>2*a*sum[i]) h++;
f[i]=f[q[h]]+a*sum[i]*sum[i]-2*a*sum[i]*sum[q[h]]+a*sum[q[h]]*sum[q[h]]+b*sum[i]-b*sum[q[h]]+c;
while(h<t && slope(q[t],q[t-1])<slope(q[t-1],i)) t--;
q[++t]=i;
}
printf("%.0lf\n",f[n]);
return 0;
}