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

地址:http://codeforces.com/contest/1453/problem/B

题意:

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

解析:

先考虑不提前改数的情况,a2~an全变成a1,前提是a3~an全变成a2,那么有:

fabs(ai-ai+1) 1<=i<=n-1

改数,怎么改是关键。肯定不能凭空乱改,可以大胆猜测是将某个数改成数组里已经存在的一个数

考虑有三个数:

一:1  5  8  原花费为7。1变成5可以将操作降为4,即a1变为a2

二:8 5  1,原花费为7。1变成5可以将操作降为4,即an变为an-1

三:5 2 10,原花费为11 ,只有2变为10,操作最小降为5,即ai+1变为ai+2。

四:5  10  2 ,原花费为11,只有10变为2,操作最小降为3,即ai+1变为ai+2。

三四可以概括为一种,减少的操作数为:abs(ai+1-ai)+abs(ai+2-ai+1)-abs(ai+2-ai)

有代码:

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int inf=99999999;
int a[maxn];
ll num[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        ll sum=0;
        for(int i=1;i<=n-1;i++)
            sum+=fabs(a[i]-a[i+1]);
        ll md=-inf;
        for(int i=1;i<=n-2;i++)
        {
            ll now=fabs(a[i+1]-a[i])+fabs(a[i+2]-a[i+1])-fabs(a[i+2]-a[i]);
            md=max(md,now);            
        }
        ll s1=0,s2=0,s3=0;
        for(int i=1;i<=n-2;i++)
        {
            s1+=fabs(a[i]-a[i+1]);
        }
        for(int i=2;i<=n-1;i++)
            s2+=fabs(a[i]-a[i+1]);
        cout<<min(min(s1,s2),sum-md)<<endl;
        
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/14146215.html