传送门:http://codeforces.com/contest/484/problem/D
题意:
给定一个包含n个元素的数组,我们可以把位置连续的数分为一组,每组至少包含一个元素。
每组对答案的贡献是这个组内最大的数和最小的数的差值。
对于单个元素组成的组,差值为0。输出答案的最大值
思路:定义i是峰值点,如果a[i-1]<=a[i]>=a[i+1]或者a[i-1]>=a[i]<=a[i+1],那么每一段中包含的峰值点一定在这一段的端点,否则从峰值点处将区间断开不会使结果变差,这也说明了存在最优解使得每一段是严格单调的,记dp[i]为把前i个数分段的最大得分,考虑i左侧最近的峰值点la,那么只需枚举la属于前一段还是后一段,于是有dp[i]=max(dp[la-1]+labs(a[i]-a[la]),dp[la]+labs(a[i]-a[la+1])),复杂度O(n)
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll __int64
const int inf=0x3f3f3f3f;
const int N=1e6+10;
ll a[N], dp[N];
int main(){
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)scanf("%I64d", &a[i]);
int la=1;
for(int i=2; i<=n; i++){
dp[i]=max(dp[la-1]+labs(a[i]-a[la]), dp[la]+labs(a[i]-a[la+1]));
if(i<n){
if(a[i-1]<=a[i] && a[i]>=a[i+1])la=i;
if(a[i-1]>=a[i] && a[i]<=a[i+1])la=i;
}
}
printf("%I64d\n", dp[n]);
return 0;
}
描述: