CF1453B

题意:给你一个长度为n的数列,首先你可以改变任意一个数(这次不算操作),之后你可以选择如下操作:

①让任意后缀都加上1

②让任意后缀都减去1

问你至少要进行几次操作,可以让数列所有数相等

思路:首先假如不改变任何数的话,我们的操作数应该是abs(a[i]-a[i-1])的前缀和。如果要改变某个数的话,只是abs(a[i]-a[i-1])和abs(a[i+1]-a[i])会发生改变,a[i-1]到a[i+1]这段会直接变成abs(a[i-1]-a[i+1]),O(1)时间就能求出答案,所以我们只要枚举每个数,假设他要改变,然后取最小值就好了。同时要注意,左右两个端点只有一个相邻的数,可以直接改变成相等的两个数,操作数直接变成0

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
ll a[N];
ll s[N];
int n;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
      int n;
      scanf("%d",&n);
      memset(s,0,sizeof(s));
      for(int i=1;i<=n;i++)
      {
        scanf("%lld",&a[i]);
        if(i>1)
            s[i]=abs(a[i]-a[i-1]);
      }
       if(n==2)//两个数直接出0
        cout<<0<<endl;
      else
      {
          ll sum=0;
        for(int i=2;i<=n;i++)
        {
          sum+=s[i];
        }
        ll ans=1e18;//这题要开ll
        for(int i=1;i<=n;i++)
        {
            if(i==1||i==n)//注意边界
            ans=min(ans,sum-s[i]-s[i+1]);
            else
            ans=min(ans,sum-s[i]-s[i+1]+abs(a[i+1]-a[i-1]));
        }
        cout<<ans<<endl;
      }
    }
return 0;
}

戒骄戒躁,百炼成钢!
原文地址:https://www.cnblogs.com/Pecoz/p/14116356.html