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优化方式例题精选】

推荐阅读