Atcoder ARC 077 E
阿新 • • 發佈:2019-02-11
題意:
你有一個遙控器用來控制電視亮度
m
,遙控器上有兩個按鍵,現在要確定一個“喜歡”亮度,使得操作次數最少。
按鍵:
- 每次把亮度+1,當亮度等於m時,按下按鍵亮度會變成1。
- 按下按鍵會直接將亮度調整的你最初設定的“喜歡”亮度。
資料範圍:
2≤n,m≤105 1≤ai≤m ai≠ai+1
演算法:
開一個桶記錄“喜歡”亮度為
i
時,能對答案產生的影響。
考慮兩個亮度之間的的操作步數,對於這兩個亮度之間的操作步數有“有效”影響的“喜歡”亮度必須是在[ai−1,ai] 之間的,並且這些影響是一個等差序列,如下圖:
怎麼維護區間加一個等差序列?
很顯然的處理方法就是差分2次這個序列,首先在x
處+1,y+1
處-1,這樣就將區間+1,那麼再字首和一次,就在區間上加了一個等差序列。
程式碼:
#include <cstdio>
#include <algorithm>
using namespace std;
int rd() {
int x = 0; char c = getchar();
while (c > '9' || c < '0') c = getchar();
while (c >= '0' && c <= '9' ) x = x * 10 + c - 48, c = getchar();
return x;
}
const int N = 2e5 + 5;
long long n, m, sum, ans = 1e18, a[N], b[N], c[N];
int main() {
n = rd(), m = rd();
for (int i = 1; i <= n; i ++) a[i] = rd();
for (int i = 2; i <= n; i ++) {
int l = a[i - 1], r = a[i];
if (l == r) continue;
if (l < r) b[l + 1] ++, b[r + 1] --, c[r + 1] -= r - l;
else b[l + 1] ++, b[r + m + 1] --, c[r + m + 1] -= r + m - l;
}
for (int i = 1; i <= 2 * m; i ++) b[i] += b[i - 1];
for (int i = 1; i <= 2 * m; i ++) c[i] += c[i - 1] + b[i];
for (int i = 1; i <= m; i ++) b[i] += b[i + m], c[i] += c[i + m], sum += b[i];
for (int i = 1; i <= m; i ++) ans = min(ans, sum - c[i] + b[i]);
printf("%lld\n", ans);
return 0;
}