CF484D Kindergarten

看着没思路就推性质呗。

如果一段数不是严格单调的可以弄成两半使得差变得至少不减少。具体构造方法如下:

  • 最大值与最小值存在一个不在两端,直接将不存在最大与最小值的一段割掉。因为差大于等于 (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;
}
原文地址:https://www.cnblogs.com/May-2nd/p/14371238.html