CF #407 DIV2 C题 区间dp

题目链接

解析:求最大的区间和问题,联系到基本的区间子段和,但是这里需要注意的是,区间的和与区间[l,r) 中的l 相关,

理所当然的解法是对数组先做绝对值差分,但是我们会发现,如果当前位置的值是abs(a[i] - a[i+1]),假如这个位置存在于某个区间[l,r)中,那么只有当i%2 == l%2的时候,才会取的原值,否则需要取相反数。即保证一个奇偶性。

那么 对于dp[i]假如认为这个状态是以差分i结尾的最大值,那么联系最大子段和,这个状态由前面的dp[i-1] (+ 或者-)abs(a[i]-a[i+1])或者就是abs(a[i]-a[i+1])得到,但是问题来了,怎么判断是+还是-。那么就和dp[i-1]是以奇数开始 还是偶数开始的区间相关了。所以接下来就很容易找出dp方程。

dp1[i]表示的是以奇数开始的区间到第i个差分的最大子段和。 

dp2[i]表示的是以偶数开始的区间到第i个差分的最大子段和。

所以dp方程:

if(i%2){
    dp1[i] = max(dp1[i-1] + v[i],v[i]);
	dp2[i] = max(dp2[i-1] - v[i],0LL);
}else{
	dp1[i] = max(dp1[i-1] - v[i],0LL);
	dp2[i] = max(dp2[i-1] + v[i],v[i]);
}

此处判断i的奇偶性就是为了能够判断出i和区间左边界l的奇偶性是否相同。

但是我们发现dp方程里面有个0,为什么不是-v[i]这个差分呢?因为假如当前i是奇数,那么对于l是偶数的dp2[i]来说,假如dp2[i-1] - v[i]的值相对v[i]较小,那么按理应该取-v[i],但是此处如果取的-v[i],表示的是dp2[i]的最大值的起点是i,但是i是奇数而dp2[i]的起点应该是偶数,这与开始设计的dp意义相违背,所以此处取0符合逻辑。

这个一维的线性dp可以做一个内存优化。

以下是dp数组的ac代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,a[100005],v[100005],dp1[100005],dp2[100005],ans =-1e17;
ll max(ll a,ll b){
	return a>b?a:b; 
}
int main(){
	
	memset(dp1,0,sizeof(dp1));
	memset(dp2,0,sizeof(dp2));
	scanf("%lld",&n);
	for(int i = 1;i<=n;i++){
		scanf("%lld",&a[i]);
		v[i-1] = abs(a[i] - a[i-1]);
	}
	for(int i = 1;i<n;i++){
		if(i%2){
			dp1[i] = max(dp1[i-1] + v[i],v[i]);
			dp2[i] = max(dp2[i-1] - v[i],0LL);
		}else{
			dp1[i] = max(dp1[i-1] - v[i],0LL);
			dp2[i] = max(dp2[i-1] + v[i],v[i]);
		}
		ans = max(ans,max(dp1[i],dp2[i]));	
	}
	printf("%lld",ans);
}

内存优化后的ac代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,a[100005],dp1 = 0,dp2 = 0,ans =-1e17;
ll max(ll a,ll b){
	return a>b?a:b; 
}
int main(){
	scanf("%lld",&n);
	for(int i = 1;i<=n;i++){
		scanf("%lld",&a[i]);
		a[i-1] = abs(a[i] - a[i-1]);
	}
	for(int i = 1;i<n;i++){
		if(i%2){
			dp1 = max(dp1 + a[i],a[i]);
			dp2 = max(dp2 - a[i],0LL);
		}else{
			dp1 = max(dp1 - a[i],0LL);
			dp2 = max(dp2 + a[i],a[i]);
		}
		ans = max(ans,max(dp1,dp2));	
	}
	printf("%lld",ans);
}

复杂度的比较:

猜你喜欢

转载自blog.csdn.net/qq_34465787/article/details/81698471