P3195 玩具装箱 题解 & 斜率优化入门

P3195 玩具装箱

简要题意:

\(n\) 个价值分别为 \(c_i\) 的玩具并给定常数 \(L\),要求将这 \(n\) 个玩具分成若干段,对于每一段区间 \([l,r]\),定义其代价为 \((r-l+\sum c_i-L)^2\),求分段的最小代价。

\(n\leq 5\times 10^4\)

分析:

定义 \(f_i\) 表示前 \(i\) 个物品分若干段的最小代价。

状态转移方程:

\[f_i=\min_{j<i}\{f_j+(sum_i-sum_j+i-j-L-1)^2\} \]

其中 \(sum_i\) 表示 \(c_i\) 的前缀和。

暴力转移,时间复杂度 \(O(n^2)\)

发现转移方程中存在 \(i,j\) 的交叉项,考虑斜率优化。

简化一下方程:令 \(s_i=sum_i+i\)\(L'=L+1\),则状态转移方程:

\[f_i=\min_{j<i}\{f_j+(s_i-s_j-L')^2\} \]

对这个式子进行变形得到:

\[f_i-(s_i-L')^2=\min_{j<i}\{f_j+{s_j}^2+2s_j(L'-s_i)\} \]

再把这个式子转化为 \(b=y-kx\) 的形式,具体地,设:

\[\begin{aligned} &x_j=s_j\\ &y_j=f_j+{s_j}^2\\ &k_i=-2(L'-s_i)\\ &b_i=f_i-(s_i-L')^2 \end{aligned} \]

此时状态转移方程为:

\[b_i=\min_{j<i}\{y_j-k_ix_j\} \]

既然要最小化 \(f_i\),而 \((s_i-L')^2\) 又是常数,问题就转化成了最小化 \(b_i\)

我们将 \((x_j,y_j)\) 看作平面上的点,\(k_i\) 表示直线的斜率,\(b_i\) 就表示一条过 \((x_j,y_j)\) 的、斜率为 \(k_i\) 的直线的截距,问题转化为选择合适的 \(j\),最小化这个截距。

因为要最小化这个截距,画一画图不难看出,可能进行转移的点集一定在下凸壳上,因此我们状态转移时只需考虑凸壳上的点,又发现本题 \(k_i\) 严格单调递增,因此我们可以利用单调队列维护凸壳。

具体地,每当遍历到一个点时,我们将先入队的斜率小的弹出,然后进行转移,转移后将后入队的不满足斜率单调性的弹出,最后把这个点加入队列,从而维护一个凸壳。

对于维护凸壳的操作,所有点最多只会进出队列一次,故均摊 \(O(1)\),总时间复杂度:\(O(n)\)

posted @ 2021-07-03 19:24  Blueqwq  阅读(72)  评论(0编辑  收藏  举报