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;
}
戒骄戒躁,百炼成钢!