AOJ 0636 フェーン現象(Foehn Phenomena)

解法

B[i] = A[i] - A[i + 1] という数列 B[i] を考えるのが良いです.
すると,A[l] から A[r] の変化が x だとすると,B[l - 1] と B[r] にしか影響を及ぼさないことがわかります.その他の場所は影響が相殺されるからです.
あとは変化によって B[l - 1],B[r] の値が正になるのか負になるのかを見てやると,あとは総和を求めるだけになるので,BITなどで管理すると頭を使わなくて楽です.

ソースコード

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
constexpr ll M = 1e9 + 7;

// 0-indexed
template <typename T>
class fenwick_tree {
public:
    fenwick_tree(int n) : n(n), dat(n, 0) {}

    void add(int i, T value) {
        for(; i<n; i |= i + 1) {
            dat[i] += value;
        }
    }

    // [0, i)
    T sum(int i) const {
        T res = 0;
        for(; i>=0; i = (i & (i+1)) - 1) {
            res += dat[i];
        }
        return res;
    }
    // [l, r)
    T sum(int l, int r) const {
        return sum(r-1) - sum(l-1);
    }

    T get(int i) const {
        return sum(i) - sum(i - 1);
    }

private:
    const int n;
    std::vector<T> dat;
};


int main() {
    ll N, Q, S, T;
    cin >> N >> Q >> S >> T;
    vector<ll> A(N + 1);
    for(int i = 0; i <= N; ++i) {
        cin >> A[i];
    }

    fenwick_tree<ll> bit(N);
    for(int i = 0; i < N; ++i) {
        if(A[i] < A[i + 1]) {
            bit.add(i, (A[i] - A[i + 1]) * S);
        } else {
            bit.add(i, (A[i] - A[i + 1]) * T);
        }
    }

    while(Q--) {
        int l, r, x;
        cin >> l >> r >> x;
        ll L = bit.get(l - 1), R = bit.get(r);
        ll new_L = L / (L < 0 ? S : T) - x;
        ll new_R = R / (R < 0 ? S : T) + x;
        bit.add(l - 1, -L + new_L * (new_L < 0 ? S : T));
        bit.add(r, -R + new_R * (new_R < 0 ? S : T));
        cout << bit.sum(0, N) << endl;
    }
}

感想

差をもった数列を扱う問題を最近解いたのですぐわかった.
こういう処理は典型らしい.
べつにBITは使わなくていいです.総和を持っておいて逐一変えるだけでOK.