1. 程式人生 > 實用技巧 >Codeforces Round #688 (Div. 2)B. Suffix Operations(思維題)

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; } }