题解:
这题和leetcode的最大子段和思路差不多,只是在最大子段和的基础上变了点形,可以先网上看下最大子段和的题解,然后这题应该就能大致知道怎么做了。
先处理数组,取相邻2个数的绝对值,然后分2种情况,从奇数点或者偶数点开始计算。具体思路见代码。
另一种做法是动态规划,求2个dp数组,表示从i开始的最大/最小和谐度,然后dp一遍即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1000010
using namespace std;
typedef long long ll;
ll a[MAXN];
ll res = 0;
int n;
int main() {
scanf("%d", &n);
for(int i = 0;i < n;i++) {
scanf("%lld", &a[i]);
}
if(n == 1) {
printf("%d\n",0);
return 0;
}
n--;
for(int i = 0;i < n;i++) {
a[i] = abs(a[i+1]-a[i]);
}
bool flag = true;//到了正数的地方
res = max(res,a[0]);
ll Max = a[0];
for(int i = 1;i < n;i++) {
flag = !flag;
if(!flag) {
// 当前是减
Max -= a[i];
if(Max <= 0) {
// 重置
Max = 0;
}
} else {
res = max(res, Max+a[i]);
Max += a[i];
}
}
if(n==1) {
printf("%lld\n",a[0]);
return 0;
}
flag = true;//到了正数的地方
res = max(res,a[1]);
Max = a[1];
for(int i = 2;i < n;i++) {
flag = !flag;
if(!flag) {
// 当前是减
Max -= a[i];
if(Max <= 0) {
// 重置
Max = 0;
}
} else {
res = max(res, Max+a[i]);
Max += a[i];
}
}
printf("%lld\n", res);
return 0;
}