斜率优化 dp
洛谷P3195 [HNOI2008] 玩具装箱
考虑设计 \(\text{dp}\),令 \(S_i=\sum_{k=1}^iC_k\),\(f_i\) 表示前 \(i\) 个玩具的最小容器费用和,则
令 \(g_i=i+S_i\),则
令
则上式变为
即,要找出一个 \(j\in[0,i-1]\),使得
且 \(b_i\) 最小.
这等价于斜率为 \(k_i\) 的直线在平面上的所有点对 \((x_j,y_j)\) 中选择一个经过使得截距最小,即斜率为 \(k_i\) 的直线从 \(y\) 轴趋于负无穷处向上平移直到交于某一点 \((x_j,y_j)\).
以下是一个例子(与本体实际情况无关):

我们发现,交点只会是所有点 \((x_j,y_j)\) 组成的下凸壳上的点,因为直线一定会先与它外部的点相交. 证明方法是将其与下凸壳上左右相邻两个点分别连线,并得出最终交于该点的斜率范围,然后证明这两个范围交集为空.
其次,设直线 \(y=kx+b\) 交下凸壳于 \(P\),设 \(l_1\) 为 \(P\) 与下凸壳上与左边点相连的线段,\(l_2\) 为 \(P\) 与下凸壳上右边点相连的线段,设 \(l_1\) 的斜率为 \(k_1\),\(l_2\) 的斜率为 \(k_2\),则 \(k_1\leq k<k_2\)(考虑到该直线与下凸壳上某边重合的情况). 于是我们在下凸壳中找到第一个斜率大于 \(k\) 的边,取其左端点即为 \((x_j,y_j)\),可以计算得到 \(b_i\). 因为下凸壳上的线段斜率依次递增,所以可以使用二分查找以 \(O(\log n)\) 的时间复杂度得到答案,其中 \(n\) 为下凸壳大小.
因为 \(C_i>0\),所以 \(S_i\) 是单调递增的,又因为 \(\text{id}\) 函数是单调递增的,所以 \(g_i\) 是单调递增的. 因为斜率 \(k_i=2(g_i-L-1)\),所以 \(k_i\) 也是单调递增的. 因此,对于每一个 \(i\),设转移点为 \(p_i\),则 \(p_i\) 是单调不减的.(类似旋转卡壳的思想). 因此,我们使用单调队列维护下凸壳,每次查询时,不断弹掉队头,直到剩下的下凸壳中,开头的线段的斜率大于 \(k_i\),此时转移点为下凸壳的左端点.
于是可以以 \(O(n)\) 的时间复杂度通过本题.
洛谷P5504 [JSOI2011] 柠檬
设 \(f_i\) 表示把前 \(i\) 个贝壳全部变为柠檬的最大柠檬数量. 设 \(w_{i,j}\) 表示区间 \([1,i]\) 中大小为 \(j\) 的贝壳的数量,则
首先,\(f\) 是单调不减的. 注意到 \(f_i\) 的转移点一定可以来自于与它贝壳大小相同的 \(j\),否则将 \(j\) 增加 \(1\) 后值不会更小.
于是转移式变为
令
则上式变为
即求最大的截距. 于是我们维护 \((x_j,y_j)\) 组成的上凸壳.

设 \(y=kx+b\) 与凸壳的交点与左边点连线得到 \(l_1\),与右边点连线得到 \(l_2\),设 \(l_1\) 的斜率为 \(k_1\),\(l_2\) 的斜率为 \(k_2\),则 \(k_1\geq k>k_2\). 于是找出第一个斜率小于 \(k\) 的线段,取其左端点,得到对应 \(j\).
于是我们对于每种贝壳大小维护一个上凸壳,可以以 \(O(n\log n)\) 的时间复杂度通过本题.
浙公网安备 33010602011771号