[OI学习笔记] 决策单调性优化dp

这篇文章主要介绍各种类型的决策单调性优化dp

考虑如下形式的dp

d p i = m i n { d p j + w ( j + 1 , i ) } j < i dp_i=min\{dp_j+w(j+1,i)\}_{j < i} dpi=min{dpj+w(j+1,i)}j<i

也可以是 m a x max max ,这里只讨论 m i n min min 的情况

对于最一般的情况,可以直接 O ( ? ) O(?) O(?) 计算 w ( i , j ) w(i,j) w(i,j) 或从 w ( i , j ) w(i,j) w(i,j) 转移到 w ( i , j + 1 ) w(i,j+1) w(i,j+1) ,可以 O ( ? n 2 ) O(?n^2) O(?n2) 进行转移

如果要更优的时间复杂度,可以进行以下优化

决策单调性优化dp,一般需要满足的形式,对于两个位置 i 1 , i 2 i_1,i_2 i1,i2 有两个决策点 x 1 , x 2 x_1,x_2 x1,x2,如果 i 1 < i 2 i_1<i_2 i1<i2 x 1 ≤ x 2 x_1 \le x_2 x1x2

如何证明?

{ d p x 1 + w ( x 1 + 1 , i 1 ) ≤ d p x 2 + w ( x 2 + 1 , i 1 ) d p x 2 + w ( x 2 + 1 , i 2 ) ≤ d p x 1 + w ( x 1 + 1 , i 2 ) \begin{cases} dp_{x_1}+w(x_1+1,i_1) \le dp_{x_2}+w(x_2+1,i_1)\\ dp_{x_2}+w(x_2+1,i_2) \le dp_{x_1}+w(x_1+1,i_2) \end{cases} {dpx1+w(x1+1,i1)dpx2+w(x2+1,i1)dpx2+w(x2+1,i2)dpx1+w(x1+1,i2)

w ( x 1 + 1 , i 1 ) − w ( x 1 + 1 , i 2 ) ≤ w ( x 2 + 1 , i 1 ) − w ( x 2 + 1 , i 2 ) w(x_1+1,i_1)-w(x_1+1,i_2) \le w(x_2+1,i_1)-w(x_2+1,i_2) w(x1+1,i1)w(x1+1,i2)w(x2+1,i1)w(x2+1,i2)

w ( x 1 + 1 , i 1 ) + w ( x 2 + 1 , i 2 ) ≤ w ( x 2 + 1 , i 1 ) + w ( x 1 + 1 , i 2 ) w(x_1+1,i_1)+w(x_2+1,i_2) \le w(x_2+1,i_1)+w(x_1+1,i_2) w(x1+1,i1)+w(x2+1,i2)w(x2+1,i1)+w(x1+1,i2)

只需证明上述不等式即可

回到决策单调性优化,最简单的一种情况,当 x x x i i i 的最优决策点时 d p y + w ( y + 1 , i ) ≥ d p x + w ( x + 1 , i ) dp_y+w(y+1,i) \ge dp_x+w(x+1,i) dpy+w(y+1,i)dpx+w(x+1,i) ,这时候只需要用一个指针维护最优决策点 x x x,一但发现决策点 x + 1 x+1 x+1 不会更劣就右移指针

大多数情况没有这么简单,一般要用一个单调栈/队列维护所有有效的决策点,对于一个决策点 x x x ,令 f x ( i ) = d p x + w ( x + 1 , i ) f_x(i)=dp_x+w(x+1,i) fx(i)=dpx+w(x+1,i) ,转移时就是找到最小的 f x ( i ) f_x(i) fx(i) ,依次枚举考虑 i i i 的过程中 i i i 是单调递增的,如果 ∀ j ≥ i f x ( j ) ≤ f y ( j ) \forall_{j \ge i} f_x(j) \le f_y(j) jifx(j)fy(j) , y y y 这个决策点就没有任何存在的价值了,可以被移除单调栈/队列

分两种情况讨论

第一种情况,对于两个决策点 x ≤ y x \le y xy , 存在一个中心点 m i d x , y mid_{x,y} midx,y 满足

{ ∀ j ≤ m i d x , y f x ( j ) < f y ( j ) ∀ j > m i d x , y f x ( j ) ≥ f y ( j ) \begin{cases} \forall_{j \le mid_{x,y}}f_x(j) < f_y(j)\\ \forall_{j > mid_{x,y}}f_x(j) \ge f_y(j) \end{cases} {jmidx,yfx(j)<fy(j)j>midx,yfx(j)fy(j)

也就是说决策点 x x x m i d mid mid 及之前是更优的,之后就完全被 y y y 取代了

在单调队列中找 i i i 的最优决策点

考虑单调队列的队首决策点 x x x 和次队首决策点 y y y ,如果发现 m i d x , y ≥ i mid_{x,y} \ge i midx,yi , x x x 就被移除队首

移除结束后发现队首决策点 x x x 就是 i i i 的最优决策点

把决策点 i i i 加入队列中时次队尾决策点 x x x ,队尾决策点 y y y ,如果 m i d y , i ≤ m i d x , y mid_{y,i} \le mid_{x,y} midy,imidx,y , y y y 就被移除队尾

移除结束后把 i i i 加入队尾

第二种情况

{ ∀ j ≤ m i d x , y f y ( j ) < f x ( j ) ∀ j > m i d x , y f y ( j ) ≥ f x ( j ) \begin{cases} \forall_{j \le mid_{x,y}}f_y(j) < f_x(j)\\ \forall_{j > mid_{x,y}}f_y(j) \ge f_x(j) \end{cases} {jmidx,yfy(j)<fx(j)j>midx,yfy(j)fx(j)

y y y m i d x , y mid_{x,y} midx,y 之后被 x x x 取代

栈顶决策点 y y y 和次栈顶决策点 x x x ,如果 m i d x , y ≥ i mid_{x,y} \ge i midx,yi , y y y 就被移除栈

栈顶决策点 x x x 即为 i i i 的最优决策点

栈顶决策点 y y y 和次栈顶决策点 x x x ,如果 m i d x , y ≤ m i d y , i mid_{x,y} \le mid_{y,i} midx,ymidy,i , y y y 就被移除栈,最后把 i i i 加入栈顶

现在的问题在于如何找到 m i d x , y mid_{x,y} midx,y

对于大多数的问题,可以二分一个 m i d mid mid log ⁡ \log log 时间复杂度内完成

但也有一部分问题 w ( i , j ) w(i,j) w(i,j) 是难以直接计算的,只能从 w ( i , j − 1 ) w(i,j-1) w(i,j1) 推出来

此时如果满足 d p i dp_i dpi d p j dp_j dpj 互不干涉,就可以二分考虑的点 i i i ,暴力找出 i i i 的最优决策点 x x x ,此时小于 i i i 的位置决策点小于等于 x x x ,大于等于 i i i 的位置决点大于等于 x x x ,这样一直递归下去即可

一般对于分层dp,从上一层的状态转移到当前层的状态满足互不干涉的性质,要求互不干涉的原因是可以在计算 i i i 之前的dp值前可以先计算出 d p i dp_i dpi

递归的时间复杂度是 O ( n log ⁡ n ) O(n \log{n}) O(nlogn)

更复杂的情况

d p i = m i n { d p j + A j B i + C j + D i } j < i dp_i = min\{dp_j+A_jB_i+C_j+D_i\}_{j < i} dpi=min{dpj+AjBi+Cj+Di}j<i

其中 A j , C j A_j,C_j Aj,Cj 只和 j j j 有关, B i , D i B_i,D_i Bi,Di 之和 i i i 有关

这时可以考虑斜率优化

转换为

d p j + C j = B i A j + D i − d p i dp_j+C_j=B_iA_j+D_i-dp_i dpj+Cj=BiAj+Didpi

形如

y = k x + b y=kx+b y=kx+b

每一个决策点 j j j 就对于平面上一个点 ( x , y ) = ( B i , d p j + C j ) (x,y)=(B_i,dp_j+C_j) (x,y)=(Bi,dpj+Cj)

B i B_i Bi 就是给定一个直线的斜率

现在要求这条给定斜率的直线穿过给定点,交 y y y 轴于点 b b b ,这时 d p i = D i − b dp_i=D_i-b dpi=Dib

d p i dp_i dpi 尽可能小只需要找到最小的 b b b 即可

根据不同题目的各个参数是否具备单调性 , 只需要以不同方式维护这些决策点 (一般是凸包) 即可解决

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值