Loading

学习笔记——四边形不等式

前言

模拟赛出四边形不等式部分分了!被我用暴力艹过了这一档部分分!

注意!文中的式子都是用了取 \(\min\) 作为转移,如果是 \(\max\) 也是一样的。细节会有所区别。

四边形不等式

定义

对于一个二元函数 \(w(a,b)\)

\(\forall a\le b\le c\le d\),都有 \(w(a,d)+w(b,c)\ge w(a,c)+w(b,d)\)

则称这个二元函数满足四边形不等式。

也就是市面上常说的:包含大于交叉

基本判定定理

如果 \(w(a,b)\) 满足对任意 \(a<b\),都有 \(w(a,b+1)+w(a+1,b)\ge w(a,b)+w(a+1,b+1)\),则 \(w(a,b)\) 满足四边形不等式。

挺显然又好证(数归),那证明就略吧。

决策单调性优化动态规划

四边形不等式不过是一个用来证明决策单调性的工具。而决策单调性才是对 dp 进行优化的关键。

1D1D 单调优化

四边形不等式可以用来优化对于形式如:

\[dp_i=\min_{0\le j<i}\{dp_j+w(j,i)\} \]

的转移式子,如果其中 \(w(a,b)\) 是满足四边形不等式的,那么这个 \(dp\) 就满足决策单调性

Proof

我们采用反证法:

假如当前有 \(a<b<c<d\),其中 \(b\)\(c\) 的最优决策点,假如 \(a\) 会是 \(d\) 的最优决策点,那么有:

\[dp_b+w(b,d)\ge dp_a+w(a,d) \]

但是根据四边形不等式,我们有:

\[w(a,d)+w(b,c)\ge w(a,c)+w(b,d) \]

将两式相加,消去同类项后得到:

\[dp_b+w(b,c)\ge dp_a+w(a,c) \]

也就是对于 \(c\) 而言,\(a\) 将会是更优的决策点,这与假设:\(b\)\(c\) 的最优决策点相矛盾。故 \(a\) 不会是 \(d\) 的最优转移点。\(\square\)

我们利用它的单调性,维护一个决策点数组 \(p\)。容易发现,\(p\) 一定是由若干段连续的相同元素构成的。然后我们在更新了 \(i\) 之后,考虑更新它之后的 \(p\),不难想到一定是更新一段后缀,所以我们只要找到这个分界点,后面用 \(i\) 作决策点更优,而前面用原来的 \(p\) 是更优的。这个东西可以二分。

实现的时候,我们用队列中存三元组的方式来代替直接维护整个 \(p\)。具体地,三元组 \((l,r,p)\) 表示 \([l,r]\) 中每个位置的当前最优决策点是 \(p\),然后把 \(p\) 数组从前往后这样压缩起来。这样在更新 \(i\) 的时候,从队头找到第一个包含 \(i\) 的(不包含可以直接弹出了),直接 \(O(1)\) 转移。然后用 \(i\) 来更新后面的 \(p\) 数组,就是从队尾一个一个弹出,如果对于当前三元组 \((l,r,p)\),对 \(l\) 来说决策点 \(p\) 劣于 \(i\),说明整个都是 \(i\) 来转移更优,那就直接弹出;否则,我们在 \([l,r]\) 之间二分找到那个分界点,然后修改队尾的 \(r\),并压入 \((ans,n,i)\),其中 \(ans\) 是第一个以 \(i\) 为最优决策点的点(也就是你二分得到的),然后结束。

我的叉点
  1. 二分注意细节,不要写错;
  2. 最后得到二分结果 \(ans\) 之后,需要判断 \(ans\) 是否大于 \(n\),否则会在之后从队尾遇到它然后产生一些错误。

例题

我们有 \(w(a,b)=\operatorname{abs}(pre_b-pre_a-L+b-a-1)^P\),满足四边形不等式,直接用上面说的优化就可以了。

My Code
const int MAXN=1e5+10;
const ll MAX=1e18;
long double pre[MAXN],dp[MAXN],L;
int P;
long double w(int l,int r){
	long double ret=abs(pre[r]-pre[l]-L+r-l-1),v=1;
	rep(i,1,P) v*=ret;return v;
}
struct RG{int l,r,p;};
string s[MAXN];
int p[MAXN];
void print(int i){
	if(p[i]) print(p[i]);
	rep(j,p[i]+1,i) cout<<s[j]<<" \n"[j==i];
}
void solve(){
	int n;cin>>n>>L>>P;
	rep(i,1,n) cin>>s[i],pre[i]=pre[i-1]+s[i].size();
	deque<RG> q;q.push_back(RG{1,n,0});
	rep(i,1,n){
		while(!q.empty()&&(q.front().r<i||q.front().l>q.front().r)) q.pop_front();
		p[i]=q.front().p;dp[i]=dp[p[i]]+w(p[i],i);q.front().l=i;
		while(!q.empty()&&dp[q.back().p]+w(q.back().p,q.back().l)>=dp[i]+w(i,q.back().l))
			q.pop_back();
		if(q.empty()){
			q.push_back(RG{i,n,i});
			continue;
		}
		int l=q.back().l,r=q.back().r,pp=q.back().p,ans=r+1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(dp[pp]+w(pp,mid)>=dp[i]+w(i,mid))
				r=mid-1,ans=mid;
			else l=mid+1;
		}
		q.back().r=ans-1;
		if(ans<=n) q.push_back(RG{ans,n,i});
	}
	if(dp[n]>MAX) cout<<"Too hard to arrange\n";
	else cout<<(ll)dp[n]<<'\n',print(n);
	cout<<"--------------------\n";
	while(!q.empty()) q.pop_back();
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;for(cin>>T;T--;)
		solve();
	return 0;
}

2D1D 分层转移优化

这种题一般具有相邻层之间转移的特征。并且同一层转移的时候具有决策单调性。这个单调性,我们同样是看 \(w(a,b)\) 是否满足四边形不等式。比如说,在我们 1D1D 优化的基础上,规定分成恰好 \(k\) 段,这样就变成了:

\[dp_{d,i}=\min_{0\le j<i}\{dp_{d-1,j}+w(j,i)\} \]

此时,我们发现与 1D1D 优化不同的是,我们在求某一层的时候,上一层的答案已经求好了,并且在当前层具有决策单调性。那考虑递归分治来 dp。即令 \(DP(l,r,p,q)\) 表示在求 \(l\sim r\) 一段的 \(dp\) 值时,最优决策点在 \(p\sim q\) 一段。然后我们求 \(mid=\dfrac{l+r}{2}\),并暴力枚举找出 \(mid\) 的最优决策点。然后根据决策单调性,分治往下做。这样复杂度是 \(O(n\log n)\) 每层,共 \(k\) 层,故复杂度优化为 \(O(nk\log n)\)

例题

看到这题容易想到枚举每个邮局控制哪段区间,就发现转移式子和上面说的是一样的。好现在我们只需要考虑 \(w(a,b)\) 是否满足四边形不等式就可以了。

首先,\(w(a,b)\) 的含义是,\(a\sim b\) 一段内放置一个邮局,使得 \(a\sim b\) 的所有村庄到这个邮局的最小距离和。不难发现,邮局一定是放在中位数的地方——如果是奇数个村庄,就放最中间的村庄处;否则就放最中间两个村庄的中间。

然后你发现这个东西是满足四边形不等式的,可以用上述优化。可惜的是,每次暴力求 \(w(a,b)\) 复杂度不够优秀。但是容易发现,这个东西可以递推。初始的时候 \(w(a,a)=0\),然后 \(w(a,b)=w(a+1,b)+d_{a+\frac{b-a+1}{2}}-d_a\) 实现转移。

这样转移就是:

\[dp_{d,i}=\min_{0\le j<i}\{dp_{d-1,j}+w(j+1,i)\} \]

递归分治优化即可。

My Code
const int MAXN=3010;
int w[MAXN][MAXN],d[MAXN],V,P;
int dp[MAXN][MAXN];
void DP(int D,int l,int r,int p,int q){
	if(l>r) return;
	int mid=(l+r)>>1,k=p,mx=dp[D-1][k]+w[k+1][mid];
	rep(i,p+1,min(q,mid-1)){
		if(dp[D-1][i]+w[i+1][mid]<mx)
			mx=dp[D-1][i]+w[i+1][mid],k=i;
	}dp[D][mid]=mx;
	DP(D,l,mid-1,p,k);DP(D,mid+1,r,k,q);
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>V>>P;
	rep(i,1,V) cin>>d[i];
	rep(len,2,V) for(int l=1;l+len-1<=V;l++){
		int r=l+len-1;
		w[l][r]=w[l+1][r]+d[l+(r-l+1)/2]-d[l];
	}
	rep(i,1,V) dp[0][i]=INF;
	rep(D,1,P) DP(D,1,V,0,V);
	cout<<dp[P][V]<<'\n';
	return 0;
}

四边形不等式对区间 dp 的优化

个人认为这不属于决策单调性的范畴,但是也是四边形不等式的重要运用之一。

区间 dp 的转移通常形如:

\[dp_{l,r}=\min_{k\in[l,r)}\{dp_{l,k}+dp_{k+1,r}\}+w(l,r) \]

我们暂时称之『区间转移式』。

区间包含单调性

为了对区间 dp 进行优化,我们需要提出这个新的概念。区间包含单调性,即对于一个二元函数 \(w(a,b)\),对于 \(a\le b\le c\le d\),满足 \(w(a,d)\ge w(b,c)\),即包含大于被包含,就称这个二元函数具有区间包含单调性。

定理

如果对于一个区间转移式,满足:

  1. \(w(a,b)\) 满足四边形不等式;
  2. \(w(a,b)\) 具有区间包含单调性;
  3. 有边界 \(w(a,a)=dp_{a,a}=0\)

则有 \(dp_{l,r}\) 满足四边形不等式。

Proof

采用数学归纳法。

\(i+1=j\) 时,\(dp_{i,j+1}+dp_{i+1,j}=dp_{i,i+2}+dp_{i+1,i+1}=dp_{i,i+2}\)

我们采用基本判定定理,要证 \(dp_{l,r}\) 满足四边形不等式,我们只要证明 \(dp_{i,j+1}+dp_{i+1,j}\ge dp_{i+1,j+1}+dp_{i,j}\)。下面进行分讨:

  • 如果对 \(dp_{i,i+2}\) 来说,最优决策点在 \(i\)\(dp_{i,i+2}=dp_{i,i}+dp_{i+1,i+2}+w(i,i+2)=w(i+1,i+2)+w(i,i+2)\ge w(i+1,i+2)+w(i,i+1)=dp_{i+1,i+2}+dp_{i,i+1}=dp_{i+1,j+1}+dp_{i,j}\)。即:\(dp_{i,j+1}+dp_{i+1,j}\ge dp_{i+1,j+1}+dp_{i,j}\)
  • 如果对 \(dp_{i,i+2}\) 来说,最优决策点在 \(i+1\)\(dp_{i,i+2}=dp_{i,i+1}+dp_{i+2,i+2}+w(i,i+2)=w(i,i+1)+w(i,i+2)\ge w(i,i+1)+w(i+1,i+2)=dp_{i+1,i+2}+dp_{i,i+1}=dp_{i+1,j+1}+dp_{i,j}\)。即:\(dp_{i,j+1}+dp_{i+1,j}\ge dp_{i+1,j+1}+dp_{i,j}\)

综上,当 \(i+1=j\) 时,上述定理成立。

接下来进行归纳。若对于 \(i+k>j\) 时,该定理成立,则证明当 \(i+k=j\) 时成立:

\(dp_{i+1,j}\) 的最优决策点为 \(x\)\(dp_{i,j+1}\) 的最优决策点为 \(y\),必然有 \(x\le y\)。此时有:

\[\begin{aligned} dp_{i+1,j}+dp_{i,j+1}&=dp_{i+1,x}+dp_{x+1,j}+w(i+1,j) \\&+dp_{i,y}+dp_{y+1,j+1}+w(i,j+1) \end{aligned}\]

而对于 \(dp_{i,j}\)\(dp_{i+1,j+1}\) 来说,这两个点必然分别是决策点之一,但不一定最优,故有:

\[\begin{aligned} dp_{i,j}+dp_{i+1,j+1}&\le dp_{i,x}+dp_{x+1,j}+w(i,j) \\&+dp_{i+1,y}+dp_{y+1,j+1}+w(i+1,j+1) \end{aligned}\]

然后根据 \(w(a,b)\) 有四边形不等式以及在 \(i+k>j\) 时,\(dp_{i,j}\) 满足四边形不等式,有:

\[w(i,j+1)+w(i+1,j)\ge w(i,j)+w(i+1,j+1)\\ dp_{i+1,x}+dp_{i,y}\ge dp_{i,x}+dp_{i+1,y}\]

代入上面推出的式子,得到 \(dp_{i+1,j}+dp_{i,j+1}\ge dp_{i,j}+dp_{i+1,j+1}\)\(\square\)

单调性

我们记 \(P_{i,j}\)\(dp_{i,j}\) 的最优决策点。则有结论:

\[P_{i,j-1}\le P_{i,j}\le P_{i+1,j} \]

Proof

我们记 \(p=P_{i,j}\),则 \(\forall k\in (i,p]\),有(已经证明 \(dp_{i,j}\) 满足四边形不等式):

\[dp_{i,p}+dp_{i+1,k}\ge dp_{i,k}+dp_{i+1,p} \]

移项,得到:

\[dp_{i+1,k}-dp_{i+1,p}\ge dp_{i,k}-dp_{i,p} \]

\(p=P_{i,j}\),则有:

\[dp_{i,k}+dp_{k+1,j}\ge dp_{i,p}+dp_{p+1,j} \]

然后将两式相加,移项,得到:

\[dp_{i+1,k}+dp_{k+1,j}\ge dp_{i+1,p}+dp_{p+1,j} \]

两边同时加上 \(w(i+1,j)\),不难发现这就是对于 \(dp_{i+1,j}\) 的两个决策点的转移式。并且我们发现,\(p\) 转移时更优的,也就是说,对于所有的 \(k\le p\),都不如用 \(p\) 转移更优,所以有 \(P_{i+1,j}\ge p=P_{i,j}\)\(\square\)

同理可以证明 \(P_{i,j}\ge P_{i,j-1}\)

应用

接下来我们运用这个单调性来优化区间 dp。

不难发现,在跑区间 dp 的时候,对于 \(dp_{i,j}\)\(P_{i,j-1}\)\(P_{i+1,j}\) 都是已经求出的,我们只要在这个区间内枚举决策点就可以了。

容易证明复杂度为 \(O(n^2)\)

方便地证明四边形不等式

为了让你能够看出某个二元函数满足四边形不等式,整理如下性质(摘自 oi-wiki):

  1. \(w_1(a,b),w_2(a,b)\) 均满足四边形不等式(或区间包含单调性),则对于任意 \(c_1,c_2\ge 0\),函数 \(w(a,b)=c_1w_1(a,b)+c_2w_2(a,b)\) 也满足四边形不等式(或区间包含单调性)。
  2. 若存在函数 \(f(x),g(x)\) 使得 \(w(l,r)=f(r)-g(l)\),则函数 \(w\) 满足四边形不等式。当函数 \(f,g\) 单调递增时,函数 \(w\) 还满足区间包含单调性。
  3. \(h(x)\) 是一个下凸[1]的增函数,\(w(a,b)\) 满足四边形不等式和区间包含单调性,则 \(h(w(a,b))\) 也满足四边形不等式和区间包含单调性。
  4. \(h(x)\) 是一个下凸的函数,\(w(a,b)\) 满足四边形不等式和区间包含单调性,则 \(h(w(a,b))\) 满足四边形不等式。

练习

一些奇怪的优化 trick 可能会出现在这里。

主要找的是决策单调性优化的题目。

\(\aleph\) 现在有 \(n\) 个人,连续的若干人可以分为一组,你要分成 \(k\) 组,使得每一组的权值和最小。定义一组人的权值为 \(\sum\limits_{i\in [1,m]}\sum\limits_{j\in [i+1,m]}u_{i,j}\),其中 \(m\) 为当前组人的个数。\(u\) 为给定的 \(n\times n\) 的矩阵。

Solution

感觉这种分组题就大概率是可以用四边形不等式优化的。

首先,我们考虑 \(w(i,j)\) 是什么。容易发现,就是 \(u\) 中横纵坐标都在 \([i,j]\) 中的所有数的和的一半。这个一半可以最后再说,所以我们直接对 \(u\) 求二维前缀和。这样就有:\(w(i,j)=u_{j,j}-u_{i-1,j}-u_{j,i-1}+u_{i-1,i-1}\),显然满足四边形不等式。

然后你发现这题可以直接套用上面邮局的做法,然后你就做完了。

\(\aleph\) 给你一个长度为 \(n\) 的序列,你要把它分成连续 \(k\) 组,使得每一组的权值和最小。一组数的权值定义为这一段中逆序对的个数。

Solution

还是非常显然的转移。然后你考虑逆序对个数是否满足四边形不等式。满足吗?满足啊!然后还是一样套个板子就写完了/qd。然后你还需要用树状数组来预处理区间逆序对的个数。

后记

能用的题好少啊,大多数都涉及到凸优化啊以及一些 wqs 二分。或者就是能用斜率优化直接艹。

那下次去学学 wqs 二分吧/qd。


  1. 指一阶导函数单调递增的函数。 ↩︎

posted @ 2022-04-24 21:13  ZCETHAN  阅读(285)  评论(0编辑  收藏  举报