代码源每日一题div1 最大权值划分

Daimayuan Online Judge

思路: d p dp dp
首先我们考虑对于某个序列的其中一段例如: [ 7 , 5 , 4 , 6 ] [7,5,4,6] [7,5,4,6]这一段拆分成: [ 7 , 5 , 4 ] [ 6 ] [7,5,4][6] [7,5,4][6]两段,那么这两种情况对于前一段的结果是不会发生变化的,那么我们放到整个序列中,其每段都一定保证着单调
但满足这一条件下,一定满足权值和最大吗?显然我们可以举出反例: [ 1 , 2 , 3 , 4 ] [ 1 ] [1,2,3,4][1] [1,2,3,4][1]不如: [ 1 , 2 , 3 ] [ 4 , 1 ] [1,2,3][4,1] [1,2,3][4,1]优,但显然这两种情况都是满足每段单调这一结论的,那么我们要考虑的就是对于某个数,它前面的数的单调情况
我们定义 d p [ i ] [ 1 ] dp[i][1] dp[i][1]是第 i i i个数在单调增子序列的最大值, d p [ i ] [ 0 ] dp[i][0] dp[i][0]是第 i i i个数在单调减子序列的最大值
我们分 a [ i ] > a [ i − 1 ] a[i]>a[i-1] a[i]>a[i1] a [ i ] < = a [ i − 1 ] a[i]<=a[i-1] a[i]<=a[i1]两种情况讨论:
a [ i ] > a [ i − 1 ] a[i]>a[i-1] a[i]>a[i1]条件下:
如果 a [ i ] a[i] a[i]在上升序列中,那么我们考虑 a [ i − 1 ] a[i-1] a[i1]的情况:
如果以 a [ i − 1 ] a[i-1] a[i1]结尾的子序列是单调增的,那么: d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] + a [ i ] − a [ i − 1 ] dp[i][1]=dp[i-1][1]+a[i]-a[i-1] dp[i][1]=dp[i1][1]+a[i]a[i1]
如果以 a [ i − 1 ] a[i-1] a[i1]结尾的子序列是单调减的,那么: d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] dp[i][1]=dp[i-1][0] dp[i][1]=dp[i1][0]
因此: d p [ i ] [ 1 ] = m a x ( d p [ i ] [ 0 ] , d p [ i − 1 ] [ 1 ] + a [ i ] − a [ i − 1 ] ) dp[i][1]=max(dp[i][0],dp[i-1][1]+a[i]-a[i-1]) dp[i][1]=max(dp[i][0],dp[i1][1]+a[i]a[i1])
a [ i ] < = a [ i − 1 ] a[i]<=a[i-1] a[i]<=a[i1]同理可得,最后我们取二者最大值即可,即: m a x ( d p [ n ] [ 1 ] , d p [ n ] [ 0 ] ) max(dp[n][1],dp[n][0]) max(dp[n][1],dp[n][0])

C o d e : Code: Code:

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n';
typedef long long ll;
typedef pair<ll,ll> PII;
const int N=1e6+10,mod=1e9+7;
int n,a[N],dp[N][2];
int main(){
	IOS;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=2;i<=n;i++){
		if(a[i]>a[i-1]) {
			dp[i][1]=max(dp[i-1][0],dp[i-1][1]+a[i]-a[i-1]);
		 	dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
		}
		else{
			dp[i][0]=max(dp[i-1][1],dp[i-1][0]+a[i-1]-a[i]);
			dp[i][1]=max(dp[i-1][0],dp[i-1][1]);
		}
	}
	cout<<max(dp[n][0],dp[n][1])<<endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会数据库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值