dp優化 | 各種dp優化方式例題精選( 三 )


發現原式轉化為 \(b_i=\min\{y_j-k_i\times x_j\}\) 。
看上去有那么億點點的像 \(y=kx+b\) 呢……
考慮這個求 \(b_i\) 的最小值的過程,就是在最小化直線的截距 。把 \((x_j,y_j)\) 看作平面上的一個點,現在有一條斜率為 \(k_i\) 的直線,從下往上找(最小化),找到的第一個點就是轉移決策點 。
實際上 , 只需維護下凸殼的那些點 。
對于本題,\(k_i\) 隨 \(i\) 的增大而增大 , 所以可以用單調隊列進行維護 。
const int N = 50010;int n, c[N], l = 1, r = 0;;ll sum[N], s[N], f[N], L;ll Get(int x) { return f[x] + (sum[x] + L) * (sum[x] + L);}long double slope(int x, int y) { return (Get(y) - Get(x)) * 1.0 / (sum[y] - sum[x]);}int main() { n = read(), L = read() + 1; for (int i = 1; i <= n; i++) c[i] = read(); for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + c[i] + 1; s[++r] = 0; for (int i = 1; i <= n; i++) {while (l < r && slope(s[l], s[l + 1]) <= (sum[i] << 1)) l++;f[i] = f[s[l]] + (sum[i] - sum[s[l]] - L) * (sum[i] - sum[s[l]] - L);while (l <= r && slope(s[r - 1], s[r]) >= slope(s[r - 1], i)) r--;s[++r] = i;}printf("%lld\n", f[n]); return 0;}N. 參考內容DP優化 - zuytong
單調隊列優化DP - superPG
【dp優化 | 各種dp優化方式例題精選】

推薦閱讀