CF1700C Helping the Nature

如果我们有一个最优的操作序列,我们可以随意重排它而不影响结果,所以不妨先处理所有的减法,把加法留到最后。也就是说,我们要先设法把序列减成同一个数。

如果直接考虑 \(a_i\) 可能没有什么头绪,所以尝试考虑差分。设 \(d_{i+1}=a_{i+1}-a_i\),我们的目标从“把所有的 \(a_i\) 变成同一个数”转化为“把所有的 \(d_i\) 变成 \(0\)”。

进而注意到,每次在前缀 \(1\sim i\) 上做一次减法,我们可能改变了很多个 \(a_i\),但是只改变了一个 \(d_{i+1}\),而 \(d_1,d_2,\cdots d_i\) 都没有变化。所以要把 \(d_{i+1}\) 变成 \(0\) 的唯一方法就是在前缀 \(1\sim i\) 上做 \(-d_{i+1}\) 次减法 \((d_{i+1}<0)\),或者在 \(i+1\sim n\) 上做 \(d_{i+1}\) 次减法 \((d_{i+1}>0)\)

所以,答案就是所有的 \(\text{abs}(d_i)\) 的和加上“最后得到的相同的数字”的绝对值。

下面是 AC 代码:

void solve() {
    using LL = long long;
    int n;
    cin >> n;
    vector<int> a(n);
    for (int &x : a) cin >> x;
    LL x = 0, y = a[0];
    for (int i = 0; i < n - 1; i++) {
        int d = a[i + 1] - a[i];
        x += abs(d);
        if (d < 0) y += d;
    }
    cout << x + abs(y) << '\n';
}
posted @ 2025-03-31 11:45  XYukari  阅读(7)  评论(0)    收藏  举报