[BZOJ1010][HNOI2008]玩具装箱

题目大意

记将 \(i\)\(j\) 合并的代价为 $ (\sum_{k = i}^j C_k + j - i - L) ^ 2$ 求总代价最小。
方便起见,全文的 \(j\) 的范围都是 \(j < i\)

解析

显然我们能有一种朴素的 \(DP\) , 记 \(f[i]\) 表示前 \(i\) 个最小的代价,\(sum[i]\) 表示 \(C_i\) 前缀和,我们有如下转移 $$f[i] = min{ f[j] + (sum[j] - sum[i] + j - i +1 - L) ^ 2 }$$
为了更加简洁的表达,我们记 \(sum[j] + j\)\(a[i]\)\(1-L\)\(l\) 则有 $$f[i] = min{ f[j] + (a[i] - a[j] - l)^2 }$$
显然如果我们暴力进行转移的话,复杂度是 \(O(n^2)\) 的,下面我们利用 \(坐标化\) 的思想,通过 \(斜率优化\) 将复杂度降为 \(O(nlogn)\)
对于我们要求的第 \(i\) 项,\(a[i]\)\(l\) 都是定值,于是原式可以化为

\[f[i] = min\{-2 * a[i] * a[j] + (f[i] + a[j]^2 + 2 * a[j] * l)\} + (a[i] - l)^2 \]

移项可以得到$$f[i] - (a[i] - l)^2=min{-2 * a[i] * a[j] + (f[i] + a[j]^2 + 2 * a[j] * l)}$$
令z = \(f[i] - (a[i] - l)^2\), \(k = 2 * a[i]\), \(x = a[j]\), \(y = (f[j] + a[j]^2 + 2 * a[j] * l)\),
原式就变成了:

\[z = min\{-k * x + y\} \]

因为要求 \(f[i]\) 最小,那么 \(z\) 要最小;对于确定的 \(j\), \(x, y\)都是定值, 所以有

\[y = k * x + z \]

因此,我们可以将求解这个问题抽象成求解所有经过 \(x_j, y_j\) 的直线中,截距最小是多少。由于 \(k\) 给定,我们不难发现答案的最优选取是在下凸包上的。由于\(a[i]\) 单调,则 \(k\) 单调,我们可以通过一个队列维护下凸包,进而降低编程复杂度。

posted @ 2018-10-04 22:22  AlessandroChen  阅读(145)  评论(0编辑  收藏  举报