文章目录

单调队列优化 DP

单调队列优化 DP

0. 定位

单调队列优化 DP,解决的是这样一类问题:
状态转移的「决策集合」是一个随主状态单调滑动的窗口,且决策的优劣可以提前与主状态 i 解耦。满足这两点时,原本 O(nm) 的枚举被改为 O(n)


1. 朴素形态与优化动机

几乎所有这类 DP 都长这样:

dp[i] = opt_{j ∈ [L(i), R(i)]} ( dp[j] + w(j, i) )
  • L(i), R(i) 是决策 j 的合法区间;
  • 若区间长度有界(如 R(i) − L(i) ≤ m),朴素枚举为 O(nm)

优化的目标只有一个:在每个 iO(1) 取出窗口内最优的 j


2. 单调队列的本质原理

2.1 它是什么

一个队首到队尾保持单调性的双端队列

  • 求区间最小 → 维护递增队列(队首最小);
  • 求区间最大 → 维护递减队列(队首最大)。

它能以 O(1) 均摊的代价,维护一个滑动窗口的最值。

2.2 它为什么能优化 DP

关键不在「队列」本身,而在决策的支配关系

  • 处理到 i 时,把候选决策 j 依次加入队列;
  • 若新决策 j₂ 比旧决策 j₁j₁ < j₂更优,且 j₂j₁ 更晚离开窗口(窗口右移,后进入者更晚被淘汰),那么 j₁j₂ 存活期间永远不可能再成为最优 → 永久淘汰 j₁
  • 于是队列里始终只保留「仍可能最优」的候选,且按优劣单调排列,队首即当前窗口最优

注:这就是「单调」的真正含义:维护的不是值的大小,而是候选决策的优劣序。只要「更优且更晚淘汰 → 永久支配」成立,结构就成立。

2.3 可分离性(拆项)

要让「j 的优劣」独立于 i,必须能把代价写成:

dp[j] + w(j, i)  =  f(j)  +  g(i)

f(j) 只与决策 j 有关,g(i) 只与主状态 i 有关。这样窗口内比较的始终是 f(j),与 i 无关,才塞得进单调队列。


3. 适用条件(判定法则)

必须同时满足以下三点才可用:

  1. 决策区间单调滑动L(i), R(i)i 非降(典型如定长窗口 [i − m, i − 1])。
  2. 目标可分离w(j, i) 能拆成 f(j) + g(i)(或更一般、对 j 单调可比的形式)。
  3. 可比较性:比较两个决策 j₁ < j₂ 的优劣时,结论不依赖 i(即 f(j₂) ≤ f(j₁) 一旦成立便恒成立)。

不满足反例w(j, i) = j · i(交叉项,优劣随 i 翻转)→ 单调队列无能为力,需斜率优化或分治优化。


4. 通用形态与模板

形式化结论:

若  dp[i] = g(i) + opt{ f(j) },   j ∈ 滑动窗口
则  用单调队列在窗口内维护 f(j),队首即 opt。

最小模板(求 min,递增队列):

dq = 双端队列,存 j 的下标
for i = 1 .. n:
    while dq 队首越出窗口: pop_front()
    dp[i] = g(i) + f(dq.front())
    while dq 非空 且 f(i) <= f(dq.back()): pop_back()   # 支配淘汰
    dq.push_back(i)

(求 max 改递减队列、比较符号反转即可。)


5. 经典模型精析

模型 A | 连续区间「至少选 1」

  • 代表:烽火传递、绿色通道。
  • 建模dp[i] = cost[i] + min{ dp[j] }j ∈ [i − m, i − 1](第 i 个必选,上一个被选者在窗口内)。
  • 优化关键:窗口内只比 dp[j],与 i 无关 → 递增队列维护 dp[j]O(n)。答案为最后 mdp 的最小值。

模型 B | 连续区间「至多选 k」

  • 代表:修剪草坪(USACO)。
  • 建模:前缀和 sdp[i] = max( dp[i−1], s[i] + max{ dp[j] − s[j] } )j ∈ [i − k, i − 1](选 i 且被选段长 ≤ k)。
  • 优化关键:把前缀和 s[i] 拆出(只与 i 有关),窗口内只比 dp[j] − s[j] → 递减队列,O(n)。与 A 对偶

模型 C | 二维滑窗最值

  • 代表:理想的正方形。
  • 建模:正方形最值 = 行方向滑窗后再列方向滑窗。
  • 优化关键:一维滑窗做两次(先每行、再每列),将 n×n 区域最值降到 O(ab)。本质是「单调队列在二维的两次投影」。

模型 D | 多重背包

  • 代表:多重背包的单调队列优化。
  • 建模dp[r + t·w] = max_m ( dp[r + m·w] − m·v ) + t·v,按 j mod w 分组。
  • 优化关键:余数固定后,体积按步长 w 等距,窗口宽度 c + 1 滑动;维护 dp[r + m·w] − m·v 的递减队列,把 O(V·c) 降到 O(V)

6. 本质再认识

  • 它 ≠ 单调栈:栈处理「固定方向第一个极值」(端点不回退);队列处理「两端都会动的窗口」。DP 优化里九成是队列。
  • 它 ≠ 斜率优化:斜率优化处理 a(i)·b(j) + c(j) 这类交叉线性项(需凸包);单调队列处理「可加性分离」项。两者都依赖「决策优劣可提前排序」。
  • 边界意识:答案取段、窗口端点——错一处即 WA。编码前务必先写清「j 的合法范围」。

7. 一句话总结

单调队列优化 DP = 决策窗口单调滑动 × 代价可加性分离。
把只与 j 有关的 f(j) 塞进双端队列,用支配关系淘汰永不为最优的旧决策,每个 iO(1) 取最优。

部分内容由 AI 润色

posted @ 2026-09-13 16:14  lvwangshu  阅读(38)  评论(0)    收藏  举报