Codeforces Round #688 (Div. 2) B
阿新 • • 發佈:2020-12-06
Codeforces Round #688 (Div. 2) B
大意
給定一個長為 \(n\) 的陣列 \(a\) ,每次可以選定一個位置 \(x\) ,將 \(a_x\sim a_n\) 同時 \(\pm1\) ,問:
如果你可以任選一個位置改成任意你想要的數字,那麼·最少多少次操作可以讓陣列各項相同。
思路
首先任選一個位置修改本質上就是刪除一個位置,也就是不用再考慮那個位置。
先考慮沒有刪除操作時我們該怎麼做。
首先,容易發現數組最後必須要等於 \(a_1\) ,因為修改過程中,任意包含在修改範圍內的 \(a_i-a_{i+1}\) 的值是不會改變的。
其次,修改順序並不會影響結果,修改本質是區間加減。
所以,我們假設最優答案的修改順序是從區間大的到區間小的,即每一次修改選取的下標都要大於等於上一次選取的下標。
那麼當某次修改後 \(a_k=a_1\) 時,不難發現 \(a_k-a_{k+1}\) 並沒有發生變化。
當經過修改後 \(a_{k+1} = a_1\) 時 \(a_{k+1}-a_{k+2}\) 也沒有發生變化。
綜上,容易得出在沒有刪除時總修改次數為 \(\Sigma|a_i-a_{i+1}|\)
現在考慮刪除,不難發現當我們刪除了 \(a_i\) 後,僅僅改變了 \(a_{i-1}\) 到 \(a_{i+1}\) 的過程,改變數為 \(|a_i-a_{i-1}|+|a_i-a_{i+1}|-|a_{i-1}-a_{i+1}|\)
顯然改變數恆大於零。
考慮刪除兩邊,改變數分別為 \(|a_1-a_2|\) 和 \(|a_n-a_{n-1}|\)
記錄之中的最大值,最後減去即可
程式碼
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; #define ll long long #define ull unsigned long long #define cint const int& #define Pi acos(-1) const int mod = 998244353; const int inf_int = 0x7fffffff; const ll inf_ll = 0x7fffffffffffffff; const double ept = 1e-9; int t, n; ll a[200200]; int main() { cin >> t; while(t--) { cin >> n; for(int i=1; i<=n; i++) cin >> a[i]; ll tmp=0, mx=0; for(int i=1; i<=n; i++) { if(i!=1) tmp += abs(a[i]-a[i-1]); if(i==1) mx = max(mx, abs(a[1]-a[2])); else if (i==n) mx = max(mx, abs(a[n]-a[n-1])); else mx = max(mx, abs(a[i]-a[i-1])+abs(a[i]-a[i+1])-abs(a[i-1]-a[i+1])); } cout << tmp-mx << endl; } return 0; }
30min...