1. 程式人生 > >Atcoder ARC 077 E

Atcoder ARC 077 E

題意:

你有一個遙控器用來控制電視亮度m,遙控器上有兩個按鍵,現在要確定一個“喜歡”亮度,使得操作次數最少。

按鍵:
  • 每次把亮度+1,當亮度等於m時,按下按鍵亮度會變成1。
  • 按下按鍵會直接將亮度調整的你最初設定的“喜歡”亮度。
資料範圍:
  • 2n,m105
  • 1aim
  • aiai+1
演算法:

開一個桶記錄“喜歡”亮度為i時,能對答案產生的影響。
考慮兩個亮度之間的的操作步數,對於這兩個亮度之間的操作步數有“有效”影響的“喜歡”亮度必須是在[ai1,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; }