决策单调性

决策单调性的解释

对于一个常见的一维 \(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\),我们需要进行如下步骤:

  1. 如果队头的 \(r\) 已经小于 \(i\),说明这个决策点已经被“淘汰”了,直接弹出队头。

  2. 当前队头就是最优决策点,使用它更新 \(f_i\)

  3. 如果在队尾的 \(l\) 处,\(i\) 比队尾的 \(p\) 更优(相当于 \(w(i,L)\le w(P,L)\),这里 \(L,P\) 为队尾的 \(l,p\)),说明队尾的 \(p\) 再也没有机会比 \(i\) 更优了,弹出队尾。

  4. 弹出所有能弹的队尾后,\(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);
}

例题:Lightning Conductor

posted @ 2025-02-03 20:27  O_v_O  阅读(60)  评论(0)    收藏  举报