[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] - (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)\),
原式就变成了:
因为要求 \(f[i]\) 最小,那么 \(z\) 要最小;对于确定的 \(j\), \(x, y\)都是定值, 所以有
因此,我们可以将求解这个问题抽象成求解所有经过 \(x_j, y_j\) 的直线中,截距最小是多少。由于 \(k\) 给定,我们不难发现答案的最优选取是在下凸包上的。由于\(a[i]\) 单调,则 \(k\) 单调,我们可以通过一个队列维护下凸包,进而降低编程复杂度。