单调队列优化DP

单调队列优化DP

 单调队列优化DP是一个很常用的技巧,主要利用DP转移的单调性来降低转移复杂度

 大体来说,单调队列优化DP的题目中状态转移具有单调性,求最优解比较常见,并且都会有一些与状态范围,取值有关的限制。引入一个具有单调性的数据结构来维护转移,并且根据限制删除不合法的转移保证合法性。

 举一个栗子:https://www.luogu.com.cn/problem/P3957

 首先,看到数据范围,直接暴力肯定是不行的。考虑二分值域,每次选一个花费来判定DP最大值是否符合要求。但是这样就必须要求每次判定的复杂度尽可能低。

 题目中给出的限制条件是在坐标轴上的距离不得超出二分的区间,于是维护一个队列和两个指针,每次更新状态时顺便更新队列,每个点入队出队各一次,时间复杂度是\(O(n)\)的。

 对队列的更新是核心操作。每次将已经转移的状态和队尾的元素比较,如果新的元素更有就将原队列元素弹出,保证队列单调不降。所以更新状态时直接取队首的元素一定最优。

 除了最优性的更新,还有合法性的要求。每次加入新元素时记录坐标,如果队首坐标非法直接弹出。


 一道更复杂的题目:https://www.luogu.com.cn/problem/P2254

 这道题首先可以得到一个\(O(nmT)\)的暴力,按滑行的顺序转移。由于每个时段操作相同,考虑分移动时段转移。

 单调队列维护时间戳和已有的最大转移。每次通过滑行得到的最大值就是队首元素加时间差,比较直接继承原来的值与滑行的优劣,并以此更新队列。维护可行性比较首尾时间差与持续时间。遇到障碍无法转移就清空队列。


 都高二了,才在NOI前搞懂最简单的DP优化,确实不应该,以后应该多练练DP

posted @ 2020-08-17 20:09  nebulyu  阅读(131)  评论(0编辑  收藏  举报