Codeforces Round #688 (Div. 2)B.Suffix Operations (思维)

在这里插入图片描述
题意:给定你一个长度为n的序列,你有两种操作,给这个序列的后缀加一或者减一,序列的后缀定义和字符串的后缀定义相同,还有你开始在所有的操作开始的时候,选择把一个数变成任意的数,这个操作不计入总的操作次数,然后问你最少需要操作几次,才能将这个序列都变成相等的数。

思路:如果不看那个额外的操作,我们想把 a 1 a_1 a1 a 2 , a 3 , . . . . a n a_2,a_3,....a_n a2,a3,....an都变成相等的,那么就一定要先把 a 2 , a 3 , . . . . a n a_2,a_3,....a_n a2,a3,....an变成相等的,同理 a 2 a_2 a2 a 3 , a 4 , . . . . a n a_3,a_4,....a_n a3,a4,....an也是这个道理,所以我们想把这些数变成相等的所花费的最少的操作一定是,相邻的两个数的绝对值之差的和。

再看加上了初始的这个操作,把某个数变成任意数,肯定也不是乱变,我们一定要把他变成他左边或者右边的数才能对这个最少操作次数起到贡献,于是我们可以比较把中间这个数变成两侧的某一数后减少的操作次数最多的就是我们要找的最优的,因为一开始总的次数其实是固定住的。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
ll a[MAXN];

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++) scanf("%lld",&a[i]);
		ll maxx = 0;
		for(int i = 1;i <= n;i ++){
			if(i == 1) maxx = max(maxx,abs(a[i]-a[i+1]));
			else if(i == n) maxx = max(maxx,abs(a[i]-a[i-1]));
			else {
				ll t = abs(a[i]-a[i-1]) + abs(a[i]-a[i+1]) - abs(a[i-1]-a[i+1]);
				maxx = max(maxx,t);
			}
			// cout<<"***"<<maxx<<"***"<<endl;
		}
		ll sum = 0;
		for(int i = 1;i < n;i ++){
			sum += abs(a[i]-a[i+1]);
		}
		sum -= maxx;
		printf("%lld\n",sum);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值