决策单调性
决策单调性的解释
对于一个常见的一维 \(dp\):\(f_i=\min/\max\{f_j+w(j,i)\}\),显然每一个点的 \(dp\) 值只能从 \(\{j|j<i\}\) 的 \(f_j\) 转移而来,我们记每一个点 \(i\) 的最优决策转移点为 \(p_i\)。
如果我们从 \(1\sim n\) 遍历 \(i\),\(p_i\) 也随之单调变化,那么这个 \(dp\) 就具有决策单调性。大部分决策单调性体现在决策点单调递增,但是也有决策点单调递减的情况(都是建立在枚举的点是从小到大的情况下)。
关于决策单调性的证明
四边形不等式
这里只考虑一维 \(dp\),它的方程形式为 \(f_i=\min\limits_{j<i}\{f_j+w(j,i)\}\)。
我们考虑 \(p_1<p_2<p_3<p_4\)。
则最小化情况下的四边形不等式表示为:\(w(p_1,p_3)+w(p_2,p_4)\le w(p_1,p_4)+w(p_2,p_3)\)。
特别的,如果等号永远成立,称为四边形恒等式。
一般记为:交叉小于包含。
定理:如果对于 \(dp\) 式 \(F\),其 \(w\) 满足四边形不等式,则 \(F\) 满足决策单调性。
证明:
反证法。记 \(f_i\) 的最优决策点为 \(p_i\),假设 \(y<x\) 且 \(p_x<p_y\)。
根据 \(F\) 的定义有:\(f_x=f_{p_x}+w(p_x,x)\le f_{p_y}+w(p_y,x)\)
不难发现 \(p_x<p_y<y<x\),故由四边形不等式:\(w(p_x,y)+w(p_y,x)\le w(p_x,x)+w(p_y,y)\)。
两式相加得到:\(f_{p_x}+w(p_x,y)\le f_{p_y}+w(p_y,y)\)。
则对于 \(y\) 来说,\(p_x\) 是一个比 \(p_y\) 更优的决策点,与条件矛盾。
故单调性得证。
决策单调性的常见优化手段
二分队列
码量较大,但适用于“在线”处理 \(f\) 数组。
考虑之前的一个结论:每一个决策点的更新范围是一段连续区间。
这意味着相邻两个决策点的更新范围之间存在着一个分界线 \(k\),当 \(i\le k\) 的时候,由前一个点 \(a_1\) 更新,之后就由后一个点 \(a_2\) 更新,并且 \(a_1\) 就被“淘汰”,再也没有机会了。
那么我们就可以维护一个单调队列。具体来说,我们的单调队列中的每一个元素是一个三元组 \(\{p,l,r\}\),分别表示当前的决策点,它能更新区间的左界,它能更新区间的右界。
考虑加入一个数 \(f_i\),我们需要进行如下步骤:
-
如果队头的 \(r\) 已经小于 \(i\),说明这个决策点已经被“淘汰”了,直接弹出队头。
-
当前队头就是最优决策点,使用它更新 \(f_i\)。
-
如果在队尾的 \(l\) 处,\(i\) 比队尾的 \(p\) 更优(相当于 \(w(i,L)\le w(P,L)\),这里 \(L,P\) 为队尾的 \(l,p\)),说明队尾的 \(p\) 再也没有机会比 \(i\) 更优了,弹出队尾。
-
弹出所有能弹的队尾后,\(i\) 就不能将队尾的 \(p\) 的区间完全覆盖了。这时我们需要二分求出两者决策区间的边界 \(K\),表示 \(K\) 以前 \(p\) 更优,\(K\) 以后 \(i\) 更优。然后把队尾的 \(r\) 设为 \(K-1\),再从队尾加入 \(\{i,K,n\}\)。
示例代码:
for(int i=1;i<=n;i++){
while(h<t&&q[h].r<i)h++;//弹队头
f[i]=w(q[h].p,i);//计算fi
while(h<t&&w(i,q[t].l)<=w(q[t].p,q[t].l))t--;//弹队尾
int L=q[t].l,R=n,an=n+1;//二分
while(L<=R){
int mi=L+R>>1;
if(w(i,mi)<=w(q[t].p,mi))
an=mi,R=mi-1;
else L=mi+1;
}
if(an>n)continue;
q[t].r=an-1;//修改,插入队尾
q[++t]={an,n,i};
}
例题:诗人小G。
分治
码量小,适用于 \(f_i\) 方程中不含有其他 \(f_j\)(相当于可以“离线”),这时使用分治。
具体来说,定义函数 \(s(l,r,L,R)\) 表示当前正在计算 \(f_l\) 到 \(f_r\) 的值,当前确定的决策点范围是 \([L,R]\)。
我们计算 \(l,r\) 的中点 \(m\),并计算出它的最优决策点 \(x\)(暴力找)。因为有决策单调性,\(f_l\) 到 \(f_{m-1}\) 的决策点一定在 \([L,x]\) 间,\(f_{m+1}\) 到 \(f_r\) 的决策点一定在 \([x,R]\) 间。于是递归 \(s(l,m-1,L,x)\) 和 \(s(m+1,r,x,R)\) 即可。
示例代码:
void sl(int l,int r,int L,int R){
if(l>r)return;
int mi=l+r>>1,an=L;
for(int i=L+1;i<=min(R,mi);i++)
if(w(mi,an)<w(mi,i))an=i;//找出最优决策点
f[mi]=max(f[mi],w(mi,an));//计算f
sl(l,mi-1,L,an);//递归
sl(mi+1,r,an,R);
}

浙公网安备 33010602011771号