决策单调性优化 DP

决策单调性优化 DP

这里面学问很深啊。优化方式也多种多样。

总的来说,对于一类形如 \(f_i=\min f_j+w(j,i)\) 的转移方程,设 \(p_i\) 为使 \(f_j+w(j,i)\) 取到最小值的点,那么如果 \(p_i\) 单调递增,我们就可以使用决策单调性优化 DP。

定理

这里给出一个定理:\(p_i\) 单调递增,当且仅当 \(w\) 满足四边形不等式,即

\[w(i,j)+w(i+1,j+1)\ge w(i,j+1)+w(i+1,j)\tag{1} \]

这个式子有更一般(但完全等价)的形式,即

\[\forall a\le b\le c\le d,w(a,c)+w(b,d)\ge w(a,d)+w(b,c)\tag{2} \]

更一般地,如果转移方程形如 \(f_i=\max f_j+w(j,i)\),那么将 \((2)\) 式若将不等号反向后成立,那么该转移同样满足决策单调性。证明基本一样。

不难用归纳法从 \((1)\) 推出 \((2)\),在 \((2)\) 中令 \(a=i,b=i+1,c=j,d=j+1\) 即得 \((1)\)

略证:四边形不等式即 \(w(i,j)-w(i,j+1)\ge w(i+1,j)-w(i+1,j+1)\)

从这个式子可以看出来,四边形不等式实际上体现了某种意义上的凸性质。

因此大多数和「次幂」(如平方,根号)有关的式子都可以猜一手决策单调性。毕竟幂函数总是凸的。

因此,考虑 \(f_i\) 的决策点 \(p_i\),由 \(p_i\) 的最优性,对于任意的 \(j<p_i\),均有

\[f_j+w(j,i)\ge f_{p_i}+w(p_i,i)\tag{3} \]

我们证明:当 \(i\) 变为 \(i+1\) 时仍有 \(f_j+w(j,i+1)\ge f_{p_i}+w(p_i,i+1)\)。下面简记 \(p\)\(p_i\)

由于 \(w\) 满足四边形不等式,因此

\[w(j,i)+w(p,i+1)\ge w(p,i)+w(j,i+1) \]

这里 \(a,b,c,d\) 分别为 \(a=j,b=p,c=i,d=i+1\)

\[\iff w(j,i)-w(j,i+1)\ge w(p,i)-w(p,i+1)\tag{4} \]

\((3)+(4)\) 即得 \(f_j+w(j,i+1)\ge f_{p_i}+w(p_i,i+1)\)。这就完成了证明。

二分队列

现在我们知道 \(p_i\) 单调递增,第一个想法是在转移时从 \(p_{i-1}\)\(i-1\) 枚举 \(j\) 尝试转移,但是这样复杂度也不对。

我们考虑直接维护 \(p_i\) 这个序列,一开始将 \(p_i\) 全部设置为 \(1\),也就是先让所有 \(f_i\) 都从 \(1\) 转移。

我们的算法可以保证在计算到 \(i\) 时,\(p_i\) 恰好就是 \(f_i\) 的最优决策点。

在计算到 \(f_i\) 时,首先由 \(p_i\) 直接计算出 \(f_i\) 的值,接下来我们将根据 \(f_i\) 的值来更新后面的决策点。

具体来说,由决策单调性我们可以知道,一旦某个地方满足 \(p_j=i\),那么后面的 \(p_{j+1\cdots n}\) 都至少是 \(i\)

而当前我们只考虑到 \(i\),也就是决策集合只有 \(1,2,\cdots,i\),因此实际上只需要找到这个位置 \(j\) 满足

  • \(f_i\) 恰好是 \(f_j\) 的最优决策点,但是 \(f_{j-1}\) 的最优决策点在 \(i\) 之前

然后把 \(p_{j\cdots n}\) 全都赋值为 \(i\) 即可。找到这样的 \(j\) 可以使用二分。根据决策单调性,这样的 \(j\) 应当满足 \(p\) 数组中目前存储的决策点中,\(j\) 之前的决策都比 \(i\) 好,\(j\) 之后的决策都比 \(i\) 差,二分出这个位置即可。

现在得到这个位置之后,我们需要对 \(j\) 后面的位置进行整体赋值。你说我会用线段树维护序列,当然可以,不过这样做复杂度似乎要 $2\log $,而用下面的方式可以做到 $1\log $。

其实说出来也没什么,把序列划分成若干极长连续段,满足每个连续段中 \(p\) 的值都相同。接下来二分完成后只需要修改 \(O(1)\) 个连续段,删除若干连续段,并插入一个连续段即可。这其实就是所谓「珂朵莉树」。

分治优化

这一种优化方式仅限 \(g\to f\) 的情形,也就是给定 \(g\),我们需要算出 \(f_i=\min_{j<i} g_j+w(j,i)\) 的情形。

我们定义 \(\text{solve}(l,r,pl,pr)\) 表示需要计算出 \(f[l\cdots r]\) 的最优决策点,并且已经确定了每个决策点都在 \([pl,pr]\) 之内。考虑找到区间中点 \(m=\lfloor(l+r)/2\rfloor\),然后暴力计算 \(f_m\) 的最优决策点 \(p_m\)

由决策单调性我们知道 \([l,m]\) 中的决策点都在 \([pl,p_m]\) 中,\([m+1,r]\) 的决策点都在 \([p_m,pr]\) 中,因此可以递归进 \(\text{solve}(l,m-1,pl,p_m)\)\((m+1,r,p_m,pr)\)

复杂度如何呢?画出分治树,分治树共 \(O(\log n)\) 层,在每一层中,所有的 \([pl,pr]\) 并起来恰好是 \([1,n]\),因此总的枚举次数不超过 \(n\log n\)。如果计算 \(w\) 的时间复杂度是 \(O(f(n))\),那么总的时间复杂度是 \(O(n\log n\times f(n))\)

你或许已经发现,如果要算 \(f\to f\) 的转移,这种方法需要在计算 \(p_m\) 时已知前面的所有 \(f\) 值。

而这是不可能的,因此这种方法只适用于 \(g\to f\) 的转移,方法一则同时适用于 \(f\to f\)\(g\to f\)

但方法一也有缺点,下面我们就会说明。

大多数情况下 \(O(f(n))=O(1)\),不过也存在少数 \(f\) 不好计算的情况。

若贡献难以在常数时间内计算

对于这类贡献,虽然 \(w(l,r)\) 难以 \(O(1)\)\(O(\log n)\) 计算,但 \(w\) 如果满足

  • 在已知 \(w(l,r)\) 的情况下,我们可以快速算出 \(w(l,r+1)\) 以及 \(w(l-1,r)\)

那么同样可以使用分治法在 \(O(n\log n\times \cdots )\) 的时间复杂度内完成转移,其中 \(\cdots\) 部分是通过 \(w(l,r)\)\(w(l,r+1)\)\(w(l-1,r)\) 的复杂度。

解决方法很暴力:我们在全局维护两个指针 \(L,R\),每次需要计算 \(w(l,r)\) 时,直接暴力将 \(L,R\) 移动至需要查询的区间。这看起来非常暴力,但是我们可以证明:

  • 按照正常的 DFS 序遍历分治树,指针的移动次数不会超过 \(O(n\log n)\)

我们把左右端点分开考虑。

对于右端点,由于它总是被设为 \(m=(l+r)/2\) 后不动,接下来递归进 \(\text{solve}(l,m-1,\cdot)\)\(\text{solve}(m+1,r,\cdot)\),因此指针总是从区间 \([l,r]\) 的某个端点移动到中点处,次数不超过 \(O(r-l)\),总的移动次数自然不超过 \(O(n\log n)\)

对于左端点,它在移动完后总是等于 \(\min(m-1,pr)\),类似右端点可以证明左端点的移动次数是 \(O(pr-pl)\) 的。因此,总的移动次数同样是 \(O(n\log n)\)

这就是分治法的优点所在,可以发现二分法是无法处理这样的贡献的。

有些文章把这种方法称为「整体二分」,我认为也有一定道理

对于 \(f\to f\) 类,且贡献难以计算的转移方程,我暂时没有好的解决办法,有鸽鸽教教我吗/kel

当决策值单峰

这里单峰(单谷)指的是,设 \(f_i\) 的最优决策点为 \(p\),则:

  • \(p\) 之前的决策值 \(f_j+w(j,i)\)\(j\) 增大单调递减,\(p\) 之后的决策值单调增。

这样,我们就可以直接维护 \(f_i\) 的最优决策点 \(p_i\),并在计算 \(f_{i+1}\) 时维护指针 \(j\)\(p_i\) 开始往后跳,一旦发现 \(f_j+w(j,i)<f_{j+1}+w(j+1,i)\) 就说明找到了峰值,可以直接用 \(f_j+w(j,i)\) 更新 \(f_i\)

由单峰的性质可以得到这样做的正确性。算法的时间复杂度是优秀的 \(O(n)\)

不难发现这同样适用于贡献难算但可以快速移动端点的情形。

二分栈

例题

POI2011 Lightning Conductor

很板的题,分 \(j<i\)\(j>i\) 讨论,看到 \(\sqrt{i-j}\) 很容易猜到凸性质,因此具有决策单调性。两种优化方式均可。

NOI2009 诗人小 G

同样是幂函数,容易猜到凸性质。不过这次只能用第一种优化方式了。

CF868F Yet Another Minimization Problem

\(k\) 层转移,贡献不好计算但可以快速移动区间端点,使用分治法,复杂度 \(O(nk\log n)\)。代码巨好写

Luogu5774 CmdOI2019 任务分配问题

区间逆序对看上去也很有次幂的味道,我们猜它满足四边形不等式。

略证:四边形不等式即 \(w(l,r+1)-w(l,r)\ge w(l+1,r+1)-w(l+1,r)\)

我们发现左边恰好是 \([l,r]\)\(<a_{r+1}\) 的元素个数,右边恰好是 \([l+1,r]\)\(<a_{r+1}\) 的元素个数

显然左边不会比右边小,这就完成了证明。类似上题,用树状数组维护区间转移即可做到 \(O(nk\log ^2n)\)

posted @ 2023-03-31 18:05  云浅知处  阅读(108)  评论(0编辑  收藏  举报