令S为前缀和,那么n方DP:
f[i]=max{f[i],f[j]+a*(S[i]-S[j])*(S[i]-S[j])+b*(S[i]-S[j])+c};
展开,移项得到:
f[j]+a*s[j]*s[j]=(2*a*s[i]+b)s[j]+f[i]- a*s[i]*s[i]-b*s[i]-c。
即以f[j]+a*s[j]*s[j]为y,s[j]为x的一次函数,用斜率优化。
因为斜率单调递减,所以维护一个单调递减的上凸壳即可。
IL DB Y(int x) {return (DB)f[x]+a*S[x]*S[x];} IL DB Slope(int x,int y) {return (Y(x)-Y(y))/(DB)(S[x]-S[y]);}
while (L<R&&(DB)2*a*S[i]+b<=Slope(q[L+1],q[L])) ++L; f[i]=f[q[L]]+a*(S[i]-S[q[L]])*(S[i]-S[q[L]])+b*(S[i]-S[q[L]])+c;
while (L<R&&Slope(i,q[R])>=Slope(q[R],q[R-1])) --R; q[++R]=i;
其实我们也可以把常数项b与s[j]的乘积也丢到y那边,斜率就变成了2*a*s[i],也是可以的,大家可以自己试试。