看着没思路就推性质呗。
如果一段数不是严格单调的可以弄成两半使得差变得至少不减少。具体构造方法如下:
- 最大值与最小值存在一个不在两端,直接将不存在最大与最小值的一段割掉。因为差大于等于 (0) 所以差的和不会减少。
- 最大值与最小值均在两端,因为不单调所以中间一定存在一个数大于最大值或小于最小值,将其归入另一边使得这部分的差大于等于原先的差。
现在要解决的问题就是端点上的数归入哪一边,DP 一下就好了。
时间复杂度 (O(n))。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define Max(x,y)((x)>(y)?x:y)
#define For(i,x,y)for(i=x;i<=(y);i++)
int read()
{
int A;
bool K;
char C;
C=A=K=0;
while(C<'0'||C>'9')K|=C=='-',C=getchar();
while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
return(K?-A:A);
}
int main()
{
ll x,y,z=0;
int n,i,a,b,c;
n=read();
if(n==1)cout<<0,exit(0);
c=read(),b=read();
y=x=abs(b-c);
For(i,3,n)
{
a=read();
if(a>b&&b>c||a<b&&b<c)x=y+abs(a-b);
else x=Max(y,z+abs(a-b));
c=b;
b=a;
z=y;
y=x;
}
cout<<x;
return 0;
}