假设当前的 DP 方程为
f i = min 0 ≤ j < i { − K ( i ) X ( j ) + Y ( j ) } + F ( i ) f_i=\min\limits_{0\leq j< i}\{-K(i)X(j)+Y(j)\} + F(i) fi=0≤j<imin{−K(i)X(j)+Y(j)}+F(i)
或
f i = max 0 ≤ j < i { − K ( i ) X ( j ) + Y ( j ) } + F ( i ) f_i=\max\limits_{0\leq j< i}\{-K(i)X(j)+Y(j)\} + F(i) fi=0≤j<imax{−K(i)X(j)+Y(j)}+F(i)
其中 F ( i ) F(i) F(i)、 K ( i ) K(i) K(i) 为关于 i i i 的函数, X ( j ) X(j) X(j)、 Y ( j ) Y(j) Y(j) 为关于 j j j 的函数。( X ( j ) X(j) X(j)、 Y ( j ) Y(j) Y(j) 中可以包含 f j f_j fj)
接下来只考虑 f i = min 0 ≤ j < i { − K ( i ) X ( j ) + Y ( j ) } + F ( i ) f_i=\min\limits_{0\leq j< i}\{-K(i)X(j)+Y(j)\} + F(i) fi=0≤j<imin{−K(i)X(j)+Y(j)}+F(i) 的情况,因为另一个与这个相似。
此时,我们设 B ( i ) B(i) B(i) 为 f i − F ( i ) f_i - F(i) fi−F(i)。方程就成为
B ( i ) = min 0 ≤ j < i { − K ( i ) X ( j ) + Y ( j ) } B(i)=\min\limits_{0\leq j< i}\{-K(i)X(j)+Y(j)\} B(i)=0≤j<imin{−K(i)X(j)+Y(j)}
对于一个一次方程 y = k x + b y=kx+b y=kx+b,其可以转换为 b = y − k x b=y-kx b=y−kx。
所以说,原方程相当于求过所有满足 0 ≤ j < i 0\leq j < i 0≤j<i 的点 ( X ( j ) , Y ( j ) ) (X(j), Y(j)) (X(j),Y(j)) 的、斜率为 K ( i ) K(i) K(i) 的一次方程在 y y y 轴的截距 b b b 的最小值 B ( i ) B(i) B(i)。
假设有一条直线 y = K ( i ) x + b y=K(i)x+b y=K(i)x+b,从 b = − ∞ b=-\infty b=−∞ 开始,不断上移,直到碰到第一个碰到的点 ( X ( j ) , Y ( j ) ) (X(j),Y(j)) (X(j),Y(j)),答案 B ( i ) = b B(i) = b B(i)=b。
这个问题可以使用凸包解决。
即求出所有满足 0 ≤ j < i 0\leq j < i 0≤j<i 的点 ( X ( j ) , Y ( j ) ) (X(j), Y(j)) (X(j),Y(j)) 组成的凸包,
(图片引用至 OI - WIKI)
然后求出凸包上斜率为 K ( i ) K(i) K(i) 的直线的切点。
我们可以用平衡树,二分, C D Q CDQ CDQ 等方法求出切点。
平衡树时间复杂度 O ( n log n ) O(n\log n) O(nlogn), C D Q CDQ CDQ 时间复杂度 O ( n log 2 n ) O(n\log^2 n) O(nlog2n),二分 O ( n log n ) O(n\log n) O(nlogn)。
如果函数 K ( i ) K(i) K(i) 满足单调性,则可以用单调队列解决,之后假设 K ( i ) K(i) K(i) 单调递增。(单调递减则类似)
单调队列储存了凸包上的一些节点 P 0 , P 1 , P 2 , . . . P_0, P_1,P_2,... P0,P1,P2,...。
若当前斜率改变为 K ( i ) K(i) K(i),我们每次判断单调队列中前两个点 P 0 , P 1 P_0,P_1 P0,P1 组成线段的斜率是否小于 K ( i ) K(i) K(i)。若小于,则删除 P 0 P_0 P0,重复刚才的步骤。反之,切点为 P 0 P_0 P0。
求出切点后,我们对应可以求出 B ( i ) B(i) B(i),也可以求出 f i f_i fi。
然后在图中添加点 ( X ( i ) , Y ( i ) ) (X(i),Y(i)) (X(i),Y(i)),往下计算 f i + 1 f_{i+1} fi+1。
维护一个动态凸包即可。