Yuhang's Blog

单调队列DP优化

2020-12-29 Coding

考虑状态转移方程: f(i)=minL(i)jR(i){g(j)}+h(i) 其中iNjM。显然暴力的转移复杂度是O(MN)。但当L(i)R(i)均单调递增,可以将转移的复杂度转移到O(N)。维护一个存储j的可能取值的单调队列Q,并当i从小到大变化时,保证:

  • 删除(因为L(i)的增加)Q中小于L(i)的元素。
  • 在(因为R(i)的增加)添加元素之前,删去Q中比添加的元素更劣的元素。设当前添加的元素为j0,则Q中一个更劣的元素j1需满足g(j0)g(j1)
    • 原因在于由于j1更早被添加,必然满足j1<j0,那么随着L(i)的增加,j1需要比j0更早地被删除,因而在j1能存在在Q中的剩余时间里,它永远不能成为被选择的元素。
  • (因为R(i)的增加)添加元素。

在需要进行状态转移时,取出队列中存在的最早的添加的元素。 考虑队列Q的代码实现。设出数组q[M]以及上下界变量lr。则:

  • l <= r表示队列中有存在元素。
  • 初值设为l=1r=0,表示队列中不存在元素。
  • q[++r]赋值是在队尾添加元素。
  • 在队列中存在元素的情况下,q[l]是取出队首元素,q[r]是取出队尾元素。
  • 在队列中存在元素的情况下,l++表示删除队首元素;r--表示删除队尾元素。

(存疑)更一般地,状态转移方程可以推广为: f(i)=minjS(i){g(j)}+h(i) 若满足 i1<i2,(i0<i1,jS(i0))jS(i1)jS(i2) (这表明当i增大时,对符合条件的j的集合的每个删除操作都是不需复原的。) 且先添加进队列的元素先被删除,则可以使用单调队列。