传送门

题意

给定数组 a a a,每次可以把后缀加一或减一,问最少操作次数

而且,你有一次改变某个 a i a_i ai的机会,可以改成任意数字


先考虑不改变某个 a i a_i ai时的答案

由于最后所有数字都要变成一样,所以当后 n − 1 n-1 n1个数字变得和 a 1 a_1 a1一样时就不需要操作了

证明

如果后 n − 1 n-1 n1个数字不是变成 a 1 a_1 a1,对 [ 1 , n ] [1,n] [1,n]同时加减多少次也无法满足条件

那么让 [ 2 , n ] [2,n] [2,n]的数字都变成 a 1 a_1 a1,前提是 [ 3 , n ] [3,n] [3,n]的数都变成 a 2 a_2 a2,否则也无法满足要求

那么不改变 a i a_i ai的话,答案就是 ∑ i = 1 n − 1 a b s ( a [ i ] − a [ i + 1 ] ) \sum\limits_{i=1}^{n-1}abs(a[i]-a[i+1]) i=1n1abs(a[i]a[i+1])

因为后缀 [ i + 1 , n ] [i+1,n] [i+1,n]变得一样了,需要操作 a b s ( a [ i ] − a [ i + 1 ] ) abs(a[i]-a[i+1]) abs(a[i]a[i+1])次变得和 a i a_i ai一样

如果改变 a i + 1 a_{i+1} ai+1的值,肯定是改成 a i + 2 a_{i+2} ai+2最优秀

这样原操作需要 a b s ( a [ i + 1 ] − a [ i + 2 ] ) + a b s ( a [ i ] − a [ i + 1 ] ) abs( a[i+1]-a[i+2] )+abs( a[i]-a[i+1] ) abs(a[i+1]a[i+2])+abs(a[i]a[i+1])

现在只需要 a b s ( a [ i ] − a [ i + 2 ] ) abs( a[i]-a[i+2] ) abs(a[i]a[i+2])

就省掉了 a b s ( a [ i + 1 ] − a [ i + 2 ] ) + a b s ( a [ i ] − a [ i + 1 ] ) − a b s ( a [ i ] − a [ i + 2 ] ) abs( a[i+1]-a[i+2] )+abs( a[i]-a[i+1] )-abs( a[i]-a[i+2] ) abs(a[i+1]a[i+2])+abs(a[i]a[i+1])abs(a[i]a[i+2])

取这个省去操作的 m a x max max即可

当然 a 1 a_1 a1也可以改成 a 2 a_2 a2,然后 a n a_n an也可以改成 a n − 1 a_{n-1} an1

对答案取 m i n min min即可

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=3e5+10;
const int mod =  998244353,G=3,Gi = 332748118;
int n,m,a[maxn],b[maxn];
signed main()
{
	int t;
	cin >> t;
	while( t-- )
	{
		cin >> n;
		for(int i=1;i<=n;i++)	cin >> a[i];
		int temp = 0,kl=0,ans1=0,ans2=0;
		for(int i=n-1;i>=1;i--)
		{
			temp += abs( a[i]-a[i+1] );
			if( i+2<=n )
				kl = max( kl,abs( a[i+1]-a[i+2] )+abs( a[i]-a[i+1] )-abs( a[i]-a[i+2] ) );
		}
		for(int i=n-2;i>=1;i--)	ans1 += abs( a[i]-a[i+1] );
		for(int i=n-1;i>=2;i--)	ans2 += abs( a[i]-a[i+1] );
		cout << min( min(ans1,ans2),temp-kl ) << endl;
	}	
}