【算法】决策单调性优化DP

news2025/3/19 8:11:43

文章目录

  • 决策单调性
      • 四边形不等式
      • 决策单调性
    • 形式1
      • 法1 分治
      • 法2 二分队列
      • 例题 P3515
      • Solution
    • 形式2
      • 例题 P3195
      • Solution
    • 形式3
      • 例题 CF833B
      • Solution
    • 形式4
      • 例题
      • Solution
    • 后话

决策单调性

四边形不等式

定义:
对于二元函数 w ( x , y ) w(x,y) w(x,y),若 ∀ a , b , c , d ∈ Z \forall a,b,c,d\in \mathbb{Z} a,b,c,dZ,且 a ≤ b ≤ c ≤ d a\le b\le c\le d abcd,都有 w ( a , d ) + w ( b , c ) ≥ w ( a , c ) + w ( b , d ) w(a,d)+w(b,c)\ge w(a,c)+w(b,d) w(a,d)+w(b,c)w(a,c)+w(b,d),则称函数 w w w 满足四边形不等式,也称它满足凸完全单调性

简记为 跨越 + + + 包含 ≥ \ge 交叉

定理1:
若函数 w ( x , y ) w(x,y) w(x,y) 满足 ∀ a , b ∈ Z , a < b \forall a,b\in \mathbb{Z},a<b a,bZ,a<b 都有 w ( a , b + 1 ) + w ( a + 1 , b ) ≥ w ( a , b ) + w ( a + 1 , b + 1 ) w(a,b+1)+w(a+1,b)\ge w(a,b)+w(a+1,b+1) w(a,b+1)+w(a+1,b)w(a,b)+w(a+1,b+1)
则函数 w w w 满足四边形不等式

证明1:
a < c a<c a<c,有 w ( a , c + 1 ) + w ( a + 1 , c ) ≥ w ( a , c ) + w ( a + 1 , c + 1 ) w(a,c+1)+w(a+1,c)\ge w(a,c)+w(a+1,c+1) w(a,c+1)+w(a+1,c)w(a,c)+w(a+1,c+1)
a + 1 < c a+1<c a+1<c,有 w ( a + 1 , c + 1 ) + w ( a + 2 , c ) ≥ w ( a + 1 , c ) + w ( a + 2 , c + 1 ) w(a+1,c+1)+w(a+2,c)\ge w(a+1,c)+w(a+2,c+1) w(a+1,c+1)+w(a+2,c)w(a+1,c)+w(a+2,c+1)
两式相加,得 w ( a , c + 1 ) + w ( a + 1 , c ) + w ( a + 1 , c + 1 ) + w ( a + 2 , c ) ≥ w ( a , c ) + w ( a + 1 , c + 1 ) + w ( a + 1 , c ) + w ( a + 2 , c + 1 ) w(a,c+1)+w(a+1,c)+w(a+1,c+1)+w(a+2,c)\ge w(a,c)+w(a+1,c+1)+w(a+1,c)+w(a+2,c+1) w(a,c+1)+w(a+1,c)+w(a+1,c+1)+w(a+2,c)w(a,c)+w(a+1,c+1)+w(a+1,c)+w(a+2,c+1)
w ( a , c + 1 ) + w ( a + 2 , c ) ≥ w ( a , c ) + w ( a + 2 , c + 1 ) w(a,c+1)+w(a+2,c)\ge w(a,c)+w(a+2,c+1) w(a,c+1)+w(a+2,c)w(a,c)+w(a+2,c+1)
同理可证, ∀ a ≤ b ≤ c , w ( a , c + 1 ) + w ( b , c ) ≥ w ( a , c ) , w ( b , c + 1 ) \forall a\le b\le c,w(a,c+1)+w(b,c)\ge w(a,c),w(b,c+1) abc,w(a,c+1)+w(b,c)w(a,c),w(b,c+1)
同理可证, ∀ a ≤ b ≤ c ≤ d \forall a\le b\le c\le d abcd, w ( a , d ) + w ( b , c ) ≥ w ( a , c ) + w ( b , d ) w(a,d)+w(b,c)\ge w(a,c)+w(b,d) w(a,d)+w(b,c)w(a,c)+w(b,d)

决策单调性

定义:
考虑转移方程 f [ i ] = min ⁡ 0 ≤ j < i ( f [ j ] + w ( j , i ) ) f[i]=\min_{0\le j <i} (f[j]+w(j,i)) f[i]=min0j<i(f[j]+w(j,i))
p [ i ] p[i] p[i] 表示 i i i 的最优决策 j j j,即让 f [ i ] f[i] f[i] 取最小值的 最小 j j j
p [ i ] p[i] p[i] [ 1 , n ] [1,n] [1,n] 上单调不减,则称 f f f 具有决策单调性

定理2:
考虑转移方程 f [ i ] = min ⁡ 0 ≤ j < i ( f [ j ] + w ( j , i ) ) f[i]=\min_{0\le j <i} (f[j]+w(j,i)) f[i]=min0j<i(f[j]+w(j,i)),若函数 w w w 满足四边形不等式,则 f f f 具有决策单调性
证明2:
∀ i ∈ [ 1 , n ] , j ∈ [ 0 , p [ i ] − 1 ] , f [ p [ i ] ] + w ( p [ i ] , i ) ≤ f [ j ] + w ( j , i ) \forall i\in [1,n],j\in[0,p[i]-1],f[p[i]]+w(p[i],i)\le f[j]+w(j,i) i[1,n],j[0,p[i]1],f[p[i]]+w(p[i],i)f[j]+w(j,i) ( 1 ) \color{red}(1) (1)
∀ i ′ ∈ [ i + 1 , n ] , j < p [ i ] < i < i ′ , w ( j , i ′ ) + w ( p [ i ] , i ) ≥ w ( j , i ) + w ( p [ i ] , i ′ ) \forall i'\in [i+1,n],j<p[i]<i<i',w(j,i')+w(p[i],i)\ge w(j,i)+w(p[i],i') i[i+1,n],j<p[i]<i<i,w(j,i)+w(p[i],i)w(j,i)+w(p[i],i)
∴ w ( p [ i ] , i ′ ) − w ( p [ i ] , i ) ≤ w ( j , i ′ ) − w ( j , i ) \therefore w(p[i],i')-w(p[i],i)\le w(j,i')-w(j,i) w(p[i],i)w(p[i],i)w(j,i)w(j,i) ( 2 ) \color{red}(2) (2)
( 1 ) \color{red}(1) (1)+ ( 2 ) \color{red}(2) (2) 得: f [ p [ i ] ] + w ( p [ i ] , i ′ ) ≤ f [ j ] + w ( j , i ′ ) f[p[i]]+w(p[i],i')\le f[j]+w(j,i') f[p[i]]+w(p[i],i)f[j]+w(j,i)
∴ p [ i ′ ] ≥ p [ i ] \color{red} \therefore p[i']\ge p[i] p[i]p[i]
所以 f f f 具有决策单调性

形式1

用于优化形如 f [ i ] = min ⁡ 1 ≤ j ≤ i w ( j , i ) f[i]=\min_{1\le j\le i} w(j,i) f[i]=min1jiw(j,i) 的转移方程。
因为我们只需要找到每一个 p [ i ] p[i] p[i],我们就可以算出每一个 f [ i ] f[i] f[i] 了,那么对于这种方法,我们有两种常见方法。

法1 分治

考虑求区间 [ 1 , n ] [1,n] [1,n] p [ i ] p[i] p[i],我们先求出 p [ m i d ] p[mid] p[mid],再把它分成两个区间 [ 1 , m i d − 1 ] [1,mid-1] [1,mid1] [ m i d + 1 , n ] [mid+1,n] [mid+1,n] 分治求解。
为什么可以呢,因为根据决策单调性, ∀ i ∈ [ m i d + 1 , n ] , p [ i ] ≥ p [ m i d ] , ∀ j ∈ [ 1 , m i d − 1 ] , p [ j ] ≤ p [ m i d ] \forall i\in[mid+1,n],p[i]\ge p[mid],\forall j\in [1,mid-1],p[j]\le p[mid] i[mid+1,n],p[i]p[mid],j[1,mid1],p[j]p[mid]
所以可以分治来求答案。
参考代码:

void solve(int l,int r,int pl,int pr){
	// 求pmid=p[mid]
	//算出 f[mid]
	solve(l,mid-1,p,pmid);
	solve(mid+1,r,pmid,pr);
}

法2 二分队列

易证,每一个决策一定是在一个区间内的,例如:
p [ i ] ( i ∈ [ 1 , 4 ] ) = 1 , p [ i ] ( i ∈ [ 5 , 9 ] ) = 3 , p [ i ] ( i ∈ [ 10 , n ] ) = k p[i](i\in[1,4])=1,p[i](i\in[5,9])=3,p[i](i \in[10,n])=k p[i](i[1,4])=1,p[i](i[5,9])=3,p[i](i[10,n])=k
所以可以维护一个单调队列,用于表示每个决策 i i i 所对应的最优转移点。
参考代码:

void solve(){
	h=1,t=0;
	for(int i=1;i<=n;i++){
		insert(i);
		if(h<=t&&q[h].r<i)
			h++;
		else
			q[h].l=i;
		f[i]=min(f[i],w(q[h].p,i));
	}
}

例题 P3515

给定一个长度为 n n n 的序列 { a n } \{a_n\} {an},对于每个 i ∈ [ 1 , n ] i\in [1,n] i[1,n] ,求出一个最小的非负整数 p p p ,使得 ∀ j ∈ [ 1 , n ] \forall j\in[1,n] j[1,n],都有 a j ≤ a i + p − ∣ i − j ∣ a_j\le a_i+p-\sqrt{|i-j|} ajai+pij

1 ≤ n ≤ 5 × 1 0 5 1 \le n \le 5\times 10^{5} 1n5×105 0 ≤ a i ≤ 1 0 9 0 \le a_i \le 10^{9} 0ai109

Solution

先变形:
p ≥ a [ j ] + ∣ i − j ∣ − a [ i ] , ∀ j ∈ [ 1 , n ] p\ge a[j]+\sqrt{|i-j|}-a[i],\forall j\in[1,n] pa[j]+ij a[i],j[1,n]

问题变为求 max ⁡ ( a [ j ] + ∣ i − j ∣ ) , ∀ j ∈ [ 1 , n ] \max(a[j]+\sqrt{|i-j|}),\forall j\in[1,n] max(a[j]+ij ),j[1,n]

考虑将序列先算一遍,翻转一次后再算一遍,最后求最大值,即变为求 max ⁡ ( a [ j ] + ∣ i − j ∣ ) , ∀ j ∈ [ 1 , i ] \max(a[j]+\sqrt{|i-j|}),\forall j\in[1,i] max(a[j]+ij ),j[1,i]

f [ i ] = max ⁡ ( a [ j ] + i − j ) f[i]=\max(a[j]+\sqrt{i-j}) f[i]=max(a[j]+ij )
此处 w ( j , i ) = i − j w(j,i)=\sqrt{i-j} w(j,i)=ij
定义 a + 1 < c a+1<c a+1<c
则有:
w ( a , c ) = c − a , w ( a + 1 , c ) = c − a − 1 , w ( a , c + 1 ) = c − a + 1 , w ( a + 1 , c + 1 ) = c − a w(a,c)=\sqrt{c-a},w(a+1,c)=\sqrt{c-a-1},w(a,c+1)=\sqrt{c-a+1},w(a+1,c+1)=\sqrt{c-a} w(a,c)=ca ,w(a+1,c)=ca1 ,w(a,c+1)=ca+1 ,w(a+1,c+1)=ca

∴ w ( a , c + 1 ) + w ( a + 1 , c ) − w ( a , c ) − w ( a + 1 , c + 1 ) = c − a − 1 + c − a + 1 − 2 c − a \therefore w(a,c+1)+w(a+1,c)-w(a,c)-w(a+1,c+1)=\sqrt{c-a-1}+\sqrt{c-a+1}-2\sqrt{c-a} w(a,c+1)+w(a+1,c)w(a,c)w(a+1,c+1)=ca1 +ca+1 2ca
d = c − a d=c-a d=ca
原式 = ( d + 1 − d ) − ( d − d − 1 ) =(\sqrt{d+1}-\sqrt{d})-(\sqrt{d}-\sqrt{d-1}) =(d+1 d )(d d1 )
对函数 f ( x ) = x − x − 1 f(x)=\sqrt{x}-\sqrt{x-1} f(x)=x x1 求导发现其单调递减,所以原式恒小于 0 0 0,即可得:
w ( a , c + 1 ) + w ( a + 1 , c ) ≤ w ( a , c ) + w ( a + 1 , c + 1 ) w(a,c+1)+w(a+1,c)\le w(a,c)+w(a+1,c+1) w(a,c+1)+w(a+1,c)w(a,c)+w(a+1,c+1)
可以发现,它跟四边形不等式符号相反,同样亦可证得 f f f 满足决策单调性,于是可以套用 法 1 1 1 和法 2 2 2 进行求解。
参考代码:
F1:

#include<bits/stdc++.h>
#define int __int128
#define lf double
using namespace std;
const int N=5e5+1,mod=1e9+7;
const lf eps=1e-5;
int n,a[N];
lf sq[N],f[N];
inline lf w(int j,int i){
	return 1.0*a[j]+sq[i-j];
}
inline int Ceil(lf x){
	return (int)(x+1-eps);
}
void solve(int l,int r,int pl,int pr){
	if(l>r)
		return ;
	int mid=(l+r)>>1,mxp;
	lf mx=0;
	for(int i=pl;i<=min(mid,pr);i++)
			if(w(i,mid)>mx)
				mx=w(i,mid),mxp=i;
	f[mid]=max(f[mid],mx);
	solve(l,mid-1,pl,mxp);
	solve(mid+1,r,mxp,pr);
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),sq[i]=sqrt((1.0*i));
	solve(1,n,1,n);
	for(int i=1;i<=n/2;i++)
		swap(a[i],a[n-i+1]),swap(f[i],f[n-i+1]);
	solve(1,n,1,n);
	for(int i=1;i<=n/2;i++)
		swap(a[i],a[n-i+1]),swap(f[i],f[n-i+1]);
	for(int i=1;i<=n;i++){
		write(Ceil(f[i]-a[i]));
		printf("\n");
	}
	return 0;
}

F2:

#include<bits/stdc++.h>
#define int __int128
#define lf double
using namespace std;
const int N=5e5+1,mod=1e9+7;
const lf eps=1e-5;
int n,a[N],h,t;
lf sq[N],f[N];
struct fy{
	int l,r,p;
}q[N];
inline lf w(int j,int i){
	return 1.0*a[j]+sq[i-j];
}
inline int Ceil(lf x){
	return (int)(x+1-eps);
}
int find_(int t,int x){
	int res=q[t].r+1,l=q[t].l,r=q[t].r,p=q[t].p;
	while(l<=r){
		int mid=(l+r)>>1;
		if(w(p,mid)<=w(x,mid))
			res=mid,r=mid-1;
		else
			l=mid+1;
	}
	return res;
}
void insert(int x){
	q[t].l=max(q[t].l,x);
	while(h<=t&&w(q[t].p,q[t].l)<=w(x,q[t].l))
		t--;
	if(h<=t){
		int mid=find_(t,x);
		if(mid>n)
			return ;
		q[t].r=mid-1;
		q[++t].l=mid,q[t].p=x,q[t].r=n;
	}
	else{
		q[++t].l=x,q[t].p=x,q[t].r=n;
	}
}
void solve(){
	h=1,t=0;
	for(int i=1;i<=n;i++){
		insert(i);
		if(h<=t&&q[h].r<i)
			h++;
		else
			q[h].l=i;
		f[i]=max(f[i],w(q[h].p,i));
	}
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),sq[i]=sqrt((1.0*i));
	solve();
	for(int i=1;i<=n/2;i++)
		swap(a[i],a[n-i+1]),swap(f[i],f[n-i+1]);
	solve();
	for(int i=1;i<=n/2;i++)
		swap(a[i],a[n-i+1]),swap(f[i],f[n-i+1]);
	for(int i=1;i<=n;i++){
		write(Ceil(f[i]-a[i]));
		printf("\n");
	}
	return 0;
}

形式2

用于优化形如 f [ i ] = min ⁡ 0 ≤ j < i ( f [ j ] + w ( j + 1 , i ) ) f[i]=\min_{0\le j<i}(f[j]+w(j+1,i)) f[i]=min0j<i(f[j]+w(j+1,i)) 的转移方程。( w w w 满足四边形不等式)
注意到此种转移方程依赖于前面的值,因此分治法不再适用,所以只能用二分队列,思路跟上面一摸一样。

例题 P3195

P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。
P 教授有编号为 1 ⋯ n 1 \cdots n 1n n n n 件玩具,第 i i i 件玩具经过压缩后的一维长度为 C i C_i Ci
为了方便整理,P教授要求:

  • 在一个一维容器中的玩具编号是连续的。
  • 同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果将第 i i i 件玩具到第 j j j 个玩具放到一个容器中,那么容器的长度将为 x = j − i + ∑ k = i j C k x=j-i+\sum\limits_{k=i}^{j}C_k x=ji+k=ijCk
    制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 x x x,其制作费用为 ( x − L ) 2 (x-L)^2 (xL)2。其中 L L L 是一个常量。P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 L L L。但他希望所有容器的总费用最小。

对于全部的测试点, 1 ≤ n ≤ 5 × 1 0 4 1 \leq n \leq 5 \times 10^4 1n5×104 1 ≤ L ≤ 1 0 7 1 \leq L \leq 10^7 1L107 1 ≤ C i ≤ 1 0 7 1 \leq C_i \leq 10^7 1Ci107

Solution

f [ i ] f[i] f[i] 表示前 i i i 个玩具装箱的最小代价,则枚举第 i i i 个玩具和那些玩具放在一个箱子中,可得转移方程:
f [ i ] = min ⁡ 1 ≤ j ≤ i ( f [ j − 1 ] + ( i − j − L + ∑ k = j i C k ) 2 ) f[i]=\min_{1\le j\le i}(f[j-1]+(i-j-L+\sum_{k=j}^iC_k)^2) f[i]=1jimin(f[j1]+(ijL+k=jiCk)2)

f f f 满足决策单调性,证明参考 OI-WIKI
在这里插入图片描述

补充:图片的 K K K 与题意中的 L L L 意思相同。
性质 1 , 2 , 3 1,2,3 1,2,3
在这里插入图片描述
那么把形式 1 1 1 例题的方法 2 2 2 的代码改装一下就可以了。
参考Code:

#include<bits/stdc++.h>
#define int __int128
#define lf double
using namespace std;
const int N=5e5+1,mod=1e9+7;
const lf eps=1e-5;
int n,a[N],h,t,L;
int f[N],sum[N];
struct fy{
	int l,r,p;
}q[N];
inline int w(int j,int i){
	return f[j-1]+(i-j+sum[i]-sum[j-1]-L)*(i-j+sum[i]-sum[j-1]-L);
}
int find_(int t,int x){
	int res=q[t].r+1,l=q[t].l,r=q[t].r,p=q[t].p;
	while(l<=r){
		int mid=(l+r)>>1;
		if(w(p,mid)>=w(x,mid))
			res=mid,r=mid-1;
		else
			l=mid+1;
	}
	return res;
}
void insert(int x){
	q[t].l=max(q[t].l,x);
	while(h<=t&&w(q[t].p,q[t].l)>=w(x,q[t].l))
		t--;
	if(h<=t){
		int mid=find_(t,x);
		if(mid>n)
			return ;
		q[t].r=mid-1;
		q[++t].l=mid,q[t].p=x,q[t].r=n;
	}
	else{
		q[++t].l=x,q[t].p=x,q[t].r=n;
	}
}
void solve(){
	h=1,t=0;
	for(int i=1;i<=n;i++){
		insert(i);
		if(h<=t&&q[h].r<i)
			h++;
		else
			q[h].l=i;
		f[i]=max(f[i],w(q[h].p,i));
	}
}
signed main(){
	n=read();
	L=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),sum[i]=sum[i-1]+a[i];
	solve();
	write(f[n]);
	return 0;
}
//直接交不能AC哦
//而且此代码与OI-WIKI的略微有些不同

形式3

用于优化形如 f [ k ] [ i ] = min ⁡ 1 ≤ j ≤ i ( f [ k − 1 ] [ j − 1 ] + w ( j , i ) ) f[k][i]=\min_{1\le j\le i}(f[k-1][j-1]+w(j,i)) f[k][i]=min1ji(f[k1][j1]+w(j,i)) 的转移方程( w w w 满足四边形不等式)
注意到其实跟形式 1 1 1 没有什么区别,因为它不依赖于这一层的值,而是依赖于上一层的值,所以既可以分治也可以二分队列。
据作者喜好(不是作者太菜),例题中只给出分治做法。

例题 CF833B

将一个长度为 n n n 的序列分为 k k k 段,使得总价值最大。
一段区间的价值表示为区间内不同数字的个数。
n ≤ 35000 , k ≤ 50 n\leq 35000,k\leq 50 n35000,k50

Solution

考虑决策单调性优化DP
f [ i ] [ j ] f[i][j] f[i][j] 表示前 j j j 个数分成 i i i 段的最小费用,则可得:

f [ i ] [ j ] = min ⁡ 1 ≤ k < j ( f [ i − 1 ] [ k ] + w ( k + 1 , j ) ) f[i][j]=\min_{1\le k<j}(f[i-1][k]+w(k+1,j)) f[i][j]=1k<jmin(f[i1][k]+w(k+1,j))
其中 w ( l , r ) w(l,r) w(l,r) 表示 下表为 [ l , r ] [l,r] [l,r] 中不同数字的个数。
证明 w w w 满足决策单调性:
手搓几个样例就可以了口糊过去
证明:
g ( x , l , r ) g(x,l,r) g(x,l,r) 表示 x x x 是否在区间 [ l , r ] [l,r] [l,r] 内出现过,出现为 0 0 0,否则为 1 1 1, Δ = [ C a = = C b + 1 ] \Delta=[C_a==C_{b+1}] Δ=[Ca==Cb+1]
w ( a , b + 1 ) + w ( a + 1 , b ) = 2 w ( a + 1 , b ) + g ( C a , a + 1 , b ) + g ( C b + 1 , a + 1 , b ) − Δ w(a,b+1)+w(a+1,b)=2w(a+1,b)+g(C_a,a+1,b)+g(C_{b+1},a+1,b)-\Delta w(a,b+1)+w(a+1,b)=2w(a+1,b)+g(Ca,a+1,b)+g(Cb+1,a+1,b)Δ
w ( a , b ) + w ( a + 1 , b + 1 ) = 2 w ( a + 1 , b ) + g ( C a , a + 1 , b ) + g ( C b + 1 , a + 1 , b ) w(a,b)+w(a+1,b+1)=2w(a+1,b)+g(C_a,a+1,b)+g(C_{b+1},a+1,b) w(a,b)+w(a+1,b+1)=2w(a+1,b)+g(Ca,a+1,b)+g(Cb+1,a+1,b)
所以可得:
w ( a , b + 1 ) + w ( a + 1 , b ) ≤ w ( a , b ) + w ( a + 1 , b + 1 ) w(a,b+1)+w(a+1,b)\le w(a,b)+w(a+1,b+1) w(a,b+1)+w(a+1,b)w(a,b)+w(a+1,b+1)
因此 w w w 满足四边形不等式
所以 f f f 满足决策单调性

仅限于分治方法:
接下来就可以 Code了,不过维护 w ( l , r ) w(l,r) w(l,r) 时注意可以用莫队的思想,维护双指针,由于分治的特殊性可以保证时间复杂度为 O ( n ) O(n) O(n)
总时间复杂度: O ( k n log ⁡ n ) O(kn\log n) O(knlogn)

参考Code:

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=1e5+1,mod=1e9+7;
int n,k,a[N],f[52][N],cnt[N],ans,l,r;
inline void add(int x){
	ans+=(++cnt[x]==1);
}
inline void del(int x){
	ans-=(--cnt[x]==0);
}
inline int w(int cl,int cr){
	while(l<cl)
		del(a[l++]);
	while(l>cl)
		add(a[--l]);
	while(r<cr)
		add(a[++r]);
	while(r>cr)
		del(a[r--]);
	return ans;
}
void solve(int l,int r,int pl,int pr,int now){
	if(l>r)
		return ;
	int mid=(l+r)>>1,mxp;
	int mx=0;
	for(int i=pl;i<=min(mid-1,pr);i++){
		int o=f[now-1][i]+w(i+1,mid);
		if(o>mx)
			mx=o,mxp=i;
	}
	f[now][mid]=max(mx,f[now-1][mid]);
	solve(l,mid-1,pl,mxp,now);
	solve(mid+1,r,mxp,pr,now);
}
signed main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	l=1,r=0;
	ans=0;
	for(int i=1;i<=k;i++){
		solve(1,n,0,n,i);
	}
	cout<<f[k][n]<<"\n";
	return 0;
}
//注意不开快读会T哦

形式4

用于优化形如 f [ i ] [ j ] = min ⁡ ( f [ i ] [ k ] + f [ k + 1 ] [ j ] + w ( i , j ) ) f[i][j]=\min(f[i][k]+f[k+1][j]+w(i,j)) f[i][j]=min(f[i][k]+f[k+1][j]+w(i,j)) 的区间DP转移方程
只需要一个简单的操作,就能把这个区间DP的时间复杂度从 O ( n 3 ) O(n^3) O(n3) 将为 O ( n 2 ) O(n^2) O(n2),就是把枚举 k k k 的代码从

for(int k=i;k<j;k++)

改为

for(int k=p[i][j-1];k<=p[i+1][j];k++)

其中 p [ i ] [ j ] p[i][j] p[i][j] 表示 i i i ~ j j j的最优分割点。
证明可以参考 《算法竞赛》中的 5.10
和洛谷 石子合并 题解区中 Hurricane、 的题解。

例题

在这里插入图片描述

Solution

在这里插入图片描述
参考代码:

#include<bits/stdc++.h>
//#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=5e3+1,mod=1e9+7;
int n,a[N],s[N],f[N][N],p[N][N];
inline int read(){
	int x=0;
	char s=getchar();
	while(s<'0'||s>'9')
		s=getchar();
	while(s>='0'&&s<='9')
		x=x*10+s-'0',s=getchar();
	return x;
}
signed main(){
//	IOS;
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=a[i+n]=read();
	for(int i=1;i<=2*n;i++)
		s[i]=s[i-1]+a[i],p[i][i]=i;
	for(int len=2;len<=n;len++)
		for(int l=1;l<=n*2-len+1;l++){
			int r=l+len-1;
			int res=1e9;
			for(int mid=p[l][r-1];mid<=p[l+1][r];mid++)
				if(f[l][mid-1]+f[mid+1][r]+s[r]-s[l-1]-a[mid]<res)
					res=f[l][mid-1]+f[mid+1][r]+s[r]-s[l-1]-a[mid],p[l][r]=mid;
			f[l][r]=res;
		}
	int ans=1e9;
	cout<<f[1][n];
	return 0;
}

后话

参考习题单
参考资料:

  1. OI-WIKI
  2. 决策单调性优化dp学习笔记
  3. 关于决策单调性优化动态规划

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1694346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux取经路】线程同步——条件变量

文章目录 前言一、条件变量1.1 pthread_cond_init——初始化一个条件变量1.2 pthread_cond_destroy——销毁一个条件变量1.3 定义一个全局的条件变量1.4 pthread_cond_wait——等待条件满足1.5 pthread_cond_signal——唤醒一个等待线程1.6 pthread_cond_broadcast——唤醒所有…

云界洞见:移动云服务开启技术创新与问题解决的新篇章

一、什么是移动云 移动云以“央企保障、安全智慧、算网一体、属地服务”为品牌支撑&#xff0c;聚焦智能算力建设&#xff0c;打造一朵智能、智慧、安全可信可控的云&#xff0c;提供更优质的算力服务&#xff0c;引领云计算产业发展。 那么下面博主带领大家了解移动云的优势所…

为什么建立数据库连接耗时?究竟耗时多久?

数据库连接从连接池中取这已经是大家的共识了&#xff0c;因为频繁的建立或者关闭连接代价太大&#xff0c;那么代价究竟有多大&#xff1f; 我们先准备一个简单的数据库连接代码段 public static void main(String[] args) throws ClassNotFoundException, SQLException, Int…

Aligned Layer:trustless应用的通用验证层

1. 引言 Aligned Layer近期获得了2000万美金的A轮融资&#xff0c;Aligned Layer&#xff1a; 致力于成为 去中心化 zero-knowledge (ZK) proof 验证层。旨在为不同证明系统&#xff0c;提供快速、经济且可扩展的零知识证明验证。作为以太坊生态系统及其他生态系统的通用sour…

都2024年了!是谁还不会优化 Hive 的小文件啊!!!速看!

文章目录 小文件产生的原因1.查询建表或者插入2.装载数据3.动态分区小文件影响解决方法针对已经存在的小文件进行优化1.小文件归档2.getmerge3.concatenate4.重写针对写入数据时的优化1.调参优化2.动态分区优化3.使用 Spark 算子控制小文件数量查看 HDFS 上的文件时,无意间点进…

1791.找出星形图的中心节点

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

蓝桥杯备赛——DP【python】

一、小明的背包1 试题链接&#xff1a;https://www.lanqiao.cn/problems/1174/learning/ 问题描述 输入实例 5 20 1 6 2 5 3 8 5 15 3 3 输出示例 37 问题分析 这里我们要创建一个DP表&#xff0c;DP&#xff08;i&#xff0c;j&#xff09;表示处理到第i个物品时消耗j体…

# 【基于随机森林算法的数据回归预测】附详细Matlab代码

文章目录 1. 引言2. 随机森林算法原理2.1 决策树基础2.2 随机森林的构建 3. 随机森林回归的实现3.1 数据准备3.2 模型训练3.3 模型预测 4. 模型评估5. 参数调优6. 结论7. 参考文献 在数据科学的世界里&#xff0c;预测模型是解决未来未知问题的关键工具。随机森林算法&#xff…

[国产大模型简单使用介绍] 开源与免费API

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 随着大模型技术蓬勃发展和开源社区越来越活跃,国内的大模型也如雨后春笋一般.这时,一些就会问了,有了llama3,Mistral还有Gemma等等,国外大厂接连发力,一些开源社区也会有一些不错的模型,国内怎么比?对一个人使用,oll…

Golang单元测试

文章目录 传统测试方法基本介绍主要缺点 单元测试基本介绍测试函数基准测试示例函数 传统测试方法 基本介绍 基本介绍 代码测试是软件开发中的一项重要实践&#xff0c;用于验证代码的正确性、可靠性和预期行为。通过代码测试&#xff0c;开发者可以发现和修复潜在的错误、确保…

小猪APP分发:一站式托管服务,轻松玩转应用市场

在当今移动应用爆炸式增长的时代&#xff0c;开发者们面临的挑战不再仅限于创意的火花和代码的实现&#xff0c;更在于如何让精心打造的应用快速触达广大用户。这正是小猪APP分发www.appzhu.net应运而生的背景——作为一个全面、高效的APP托管服务分发平台&#xff0c;它为开发…

相关服务器介绍

服务器是一种高性能的计算机&#xff0c;它被设计用来为其他计算机或终端设备提供服务&#xff0c;如数据处理、文件存储、网络通信等。服务器通常具有强大的计算能力、大容量的存储空间和高效的网络连接能力。 常见的服务器种类及其特点 文件服务器 文件服务器主要负责中央存储…

什么是JDK21虚拟线程

JDK21虚拟线程 1. 来一段小故事2. 什么是虚拟线程3. 虚拟线程的几个关键特点4.细说关键特点1.为什么轻量级的1.传统线程运行时间2.虚拟线程运行时间3.对垃圾回收的影响 2.非绑定OS线程的魅力所在3.和传统相比为何易于使用4.阻塞优化有什么好处1.什么是阻塞优化2.JDK 21虚拟线程…

基于SSH的母婴用品销售管理系统带万字文档

文章目录 母婴商城系统一、项目演示二、项目介绍三、系统部分功能截图四、万字论文参考五、部分代码展示六、底部获取项目源码和万字论文参考&#xff08;9.9&#xffe5;带走&#xff09; 母婴商城系统 一、项目演示 母婴商城系统 二、项目介绍 基于SSH的母婴商城系统 系统…

海外仓储管理系统:提升效率,标准化海外仓管理,科技赋能业务

海外仓作为跨境物流的关键一环&#xff0c;完全可以说海外仓的效率直接决定了后续物流的整体运作效率。 对于海外仓而言&#xff0c;一套高效&#xff0c;易用的海外仓储系统&#xff0c;无疑将成为提升企业竞争力的重要工具&#xff0c;帮助海外仓实现从野蛮生长到标准化管理…

边用边充电影响寿命吗?看看计算机指令组成与操作类型

计算机指令集体系结构之指令 指令由操作码和地址码字段组成。 操作码指明了指令要完成的操作。 长度可以固定&#xff1a;比如RISC&#xff08;reduced instruction set computer&#xff09;精简指令集计算机 与之对应的RISC&#xff08;复杂指令集计算机&#xff09;&…

【C++进阶】AVL树

0.前言 前面我们已经学习过二叉搜索树了&#xff0c;但如果我们是用二叉搜索树来封装map和set等关联式容器是有缺陷的&#xff0c;很可能会退化为单分支的情况&#xff0c;那样效率就极低了&#xff0c;那么有没有方法来弥补二叉搜索树的缺陷呢&#xff1f; 那么AVL树就出现了&…

【C++】类与对象——多态详解

目录 一、多态的定义 二、重载、覆盖(重写)、隐藏(重定义)的对比 三、析构函数重写 四、C11 override 和 final 1. final 2. override 五、抽象类 六、多态的原理 一、多态的定义 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产生了不同的行为…

【机器学习】机器学习与大型预训练模型的前沿探索:跨模态理解与生成的新纪元

&#x1f512;文章目录&#xff1a; &#x1f4a5;1.引言 ☔2.跨模态理解与生成技术概述 &#x1f6b2;3.大型预训练模型在跨模态理解与生成中的应用 &#x1f6f4;4.前沿探索与挑战并存 &#x1f44a;5.未来趋势与展望 &#x1f4a5;1.引言 近年来&#xff0c;机器学习领…

使用C/C++ API接口操作 Zookeeper 数据

ZooKeeper 支持 Java 和 C 的API接口。本文将介绍使用 C/C 语言客户端库的编译安装和使用入门。 一、编译安装 PS&#xff1a;就在上一篇文章还觉得安装和配置 jdk 、maven 麻烦&#xff0c;所以当时选择 apache-zookeeper-[version]-bin.tar.gz 的版本。然而&#xff0c;本文…