Codeforces Round #688 (Div. 2)B. Suffix Operations(思維題)
阿新 • • 發佈:2020-12-16
地址: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; } }