P2300 合并神犇(单调队列优化dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2300 合并神犇(单调队列优化dp)相关的知识,希望对你有一定的参考价值。

P2300 合并神犇(单调队列优化dp)

f i f_i fi​表示前 i i i​个数的最少合并次数, g i g_i gi​表示在 f i f_i fi​条件下的最小结尾值。

有转移方程: f i = m i n ( f j + i − j − 1 ) , s ( j , i ) ≥ g j f_i=min(f_j+i-j-1),s(j,i)\\ge g_j fi=min(fj+ij1),s(j,i)gj

因为: f j + 1 ≤ f j + 1 f_{j+1}\\le f_j+1 fj+1fj+1​ 即 j + 1 j+1 j+1 f j + 1 f_{j+1} fj+1至多会加1, 而 j j j 1 , i + j − 1 1,i+j-1 1,i+j1 必定会减 1 1 1

因此在满足 s ( j , i ) ≥ g j s(j,i)\\ge g_j s(j,i)gj 的情况下,肯定 j j j越大越好。

s i − s j ≥ g j → s i ≥ s j + g j s_i-s_j\\ge g_j \\rightarrow s_i\\ge s_j+g_j sisjgjsisj+gj

因此考虑单调队列维护 s j + g j s_j+g_j sj+gj ,然后每次选择满足 s j + g j ≤ s i s_j+g_j \\le s_i sj+gjsi 的条件下靠近队尾的,因为靠近队尾的 j j j更大。

然后维护一个单调递增的单调队即可,注意 n o d e node node​ 除了记录 s j + g j s_j+g_j sj+gj​ ,还要记录 j j j​这个 i d id id​ 便于转移。

另外需要注意的是队列最开始要加入 ( 0 , 0 ) (0,0) (0,0)这个结点,因为有可能直接前面所有的数为为一组进行转移。

时间复杂度: O ( n ) O(n) O(n)

// Problem: P2300 合并神犇
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2300
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-08-10 10:02:52
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
ll f[N],g[N];
ll a[N];
int n;
int l=1,r=1;//这里相当于加入了(0,0) 因为有可能直接从(0,0) 转移
struct node{
	int id;
	ll w;
}q[N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]),a[i]+=a[i-1];
	}
	for(int i=1;i<=n;i++){
		while(l+1<=r&&q[l+1].w<=a[i]) l++;
		f[i]=f[q[l].id]+i-q[l].id-1,g[i]=a[i]-a[q[l].id];
		while(l<=r&&a[i]+g[i]<=q[r].w) r--;
		q[++r]={i,a[i]+g[i]};
	}
	printf("%lld\\n",f[n]);
	return 0;
}

以上是关于P2300 合并神犇(单调队列优化dp)的主要内容,如果未能解决你的问题,请参考以下文章

P2300 合并神犇(DP)

luogu P2300 合并韩雨辰神犇

Gym - 101234J Zero Game (单调队列优化dp)

单调队列以及单调队列优化DP

单调队列优化dp

POJ2373 Dividing the Path(单调队列优化dp)