于是对于这题我们对于斜率优化做法可以总结如下:
1.用一个单调队列来维护解集。
2.假设队列中从头到尾已经有元素a b c。那么当d要入队的时候,我们维护队列的下凸性质,即如果k[d,c]<=k[c,b],那么就将c点删除。直到找到k[d,x]>k[x,y]为止,并将d点加入在该位置中。
3.找最佳决策点时,设当前求解状态为i,从队头开始,如果已有元素a b c,当i点要求解时,如果k[b,a]<=2∗sum[i],那么说明b点比a点更优,a点可以排除,于是a出队,直到第一次遇到k[j,j−1]>2∗sum[i],此时j-1即为最佳决策点。
参考代码:
#include<bits/stdc++.h>usingnamespace std;constint MAXN =500005;int n, m, s, t, dq[MAXN];int sum[MAXN], f[MAXN];inlineintGetup(int i,int j){return f[i]+ sum[i]*sum[i]- f[j]- sum[j]*sum[j];}//Yi-YjinlineintGetdown(int i,int j){return sum[i]- sum[j];}//Xi-Xjint main (){int x;while(scanf("%d%d",&n,&m)==2){for(int i =1; i <= n; i++)scanf("%d",&x), sum[i]= sum[i-1]+ x;
f[0]=0; s = t =0; dq[t++]=0;for(int i =1; i <= n; i++){while(t-s >1&&Getup(dq[s+1], dq[s])<= sum[i]*2*Getdown(dq[s+1], dq[s])) s++;
f[i]= f[dq[s]]+(sum[i]- sum[dq[s]])*(sum[i]- sum[dq[s]])+ m;while(t-s >1&&Getup(i, dq[t-1])*Getdown(dq[t-1], dq[t-2])<=Getup(dq[t-1], dq[t-2])*Getdown(i, dq[t-1])) t--;
dq[t++]= i;}printf("%d
", f[n]);}}