四边形不等式

我也不知道我为啥整这玩意
以下内容来自pl_er的讲课:

决策单调性优化 dp

对于转移

dpj=mini<j(fi+w(i,j))

t(i,j) 表示从 i 转移到 jjdp

若有对于任意 i<j,存在 k 使得对于 d[0,k]t(i,d)t(j,d)d[k+1,n]t(i,d)>t(j,d) 我们就说这个转移具有决策单调性。

容易发现决策单调性具有的性质,决策点单调不减。

如何判断是否满足决策单调性

最常见的方法是证明 w 满足四边形不等式,及

p1p2p3p4w(p1,p3)+w(p2,p4)w(p1,p4)+w(p2,p3)

可以联想四边形记忆。

下面给出证明

i<j<k1<k2t(i,k1)>t(j,k1)t(i,k2)t(j,k2)w(i,k1)+w(j,k2)w(i,k2)+w(j,k1)t(i,k2)+w(i,k1)+w(j,k2)w(i,k2)+w(j,k1)+t(j,k2)t(i,k1)t(j,k1)

接下来我们考虑如何利用决策单调性优化 dp

介绍两种方法,分治法和二分栈

先介绍分治法,分治利用的是决策点的单调性,一般认为有两种情况:

转移来自"上层",f 为其他已知数列

转移来自"本层",f 即为 dp.

对于来自上层的处理,我们直接分治处理就可以了。

来自题目

SDOI2016征途

int w(int l,int r){
	return dp[now-1][l]+(a[r]-a[l])*(a[r]-a[l]);
}
void solve(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)/2;
	int p=L,nw=1e9;
	for(int i=L;i<=R;i++){
		int tmp=w(i,mid);
		if(tmp<nw) p=i,nw=tmp;
	}
	dp[now][mid]=nw;
	solve(l,mid-1,L,p);
	solve(mid+1,r,p,R);
}
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=m;i++){
	now=i;
	solve(1,n,0,n-1);
}
printf("%lld",1ll*dp[m][n]*m-1ll*a[n]*a[n]);

对于来自本层的,我们还需要再嵌套一层分治,且用到定义。

来自题目玩具装箱

void Div(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)/2;
	int p=L;
	long long nw=1e18;
	for(int i=L;i<=R;i++){
		long long tmp=zy(i,mid);
		if(tmp<nw) nw=tmp,p=i;
	}
	dp[mid]=min(nw,dp[mid]);
	Div(l,mid-1,L,p);
	Div(mid+1,r,p,R);
}
void solve(int l,int r){
	if(l==r) return;
	int mid=(l+r)/2;
	solve(l,mid);
	Div(mid+1,r,l,mid);
	solve(mid+1,r);
}
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
solve(0,n);

二分栈方法,用的是原定义,不需要区分 f 是否为 dp

来自题目玩具装箱

int head=1,tail=0;
qu[++tail]=Node(0,1,n);
for(int i=1;i<=n;i++){
	while(qu[head].r<i) head++;
	dp[i]=zy(qu[head].x,i);
	while(head<=tail&&zy(qu[tail].x,qu[tail].l)>=zy(i,qu[tail].l)) tail--;
	if(head>tail){
		qu[++tail]=Node(i,i+1,n);
		continue;
	}
	int l=max(qu[tail].l,i+1),r=qu[tail].r;
	while(l<=r){
		int mid=(l+r)/2;
		if(zy(qu[tail].x,mid)>=zy(i,mid)) r=mid-1;
		else l=mid+1;
	}
	qu[tail].r=r;
	if(l<=n) qu[++tail]=Node(i,l,n);
}
posted @   2K22  阅读(98)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示