思路:
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[i−1]和
a
[
i
]
<
=
a
[
i
−
1
]
a[i]<=a[i-1]
a[i]<=a[i−1]两种情况讨论:
a
[
i
]
>
a
[
i
−
1
]
a[i]>a[i-1]
a[i]>a[i−1]条件下:
如果
a
[
i
]
a[i]
a[i]在上升序列中,那么我们考虑
a
[
i
−
1
]
a[i-1]
a[i−1]的情况:
如果以
a
[
i
−
1
]
a[i-1]
a[i−1]结尾的子序列是单调增的,那么:
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[i−1][1]+a[i]−a[i−1]
如果以
a
[
i
−
1
]
a[i-1]
a[i−1]结尾的子序列是单调减的,那么:
d
p
[
i
]
[
1
]
=
d
p
[
i
−
1
]
[
0
]
dp[i][1]=dp[i-1][0]
dp[i][1]=dp[i−1][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[i−1][1]+a[i]−a[i−1])
a
[
i
]
<
=
a
[
i
−
1
]
a[i]<=a[i-1]
a[i]<=a[i−1]同理可得,最后我们取二者最大值即可,即:
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;
}