#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;

    vector<long long> a(n + 2); // a[1..n]
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }

    // !!构建差分数组 d[1..n+1]
    vector<long long> d(n + 2, 0);
    for (int i = 1; i <= n; ++i) {
        d[i] = a[i] - a[i - 1];
    }




    // m 次操作,每次修改区间 [l, r] 加上 k
    for (int i = 0; i < m; ++i) {
        int l, r;
        long long k;
        cin >> l >> r >> k;
        d[l] += k;
        d[r + 1] -= k;
    }

    // 还原最终数组:前缀和
    for (int i = 1; i <= n; ++i) {
        a[i] = a[i - 1] + d[i];
        cout << a[i] << " ";
    }
    cout << endl;

    return 0;
}

朴素写法是:

for (int i = l; i <= r; ++i) {
    a[i] += k;
}

坏处:每次操作都是 O(r−l+1),多次就会超时。

✅ 差分数组思想:用一种技巧,让区间修改变成“常数时间”

我们定义一个新的数组 d[i],表示:

d[i] = a[i] - a[i-1]

也就是说,d 数组是 a 数组的“变化量”

举个例子:

a = [1, 2, 3, 4, 5]
=> d = [1, 1, 1, 1, 1] (因为 a[i]-a[i-1] 都是1)

现在我们想把区间 [2,4] 加上 10,该怎么办呢?

只需要改两项:

d[2] += 10;
d[5] -= 10;  // 4的下一位是5

🤔 为什么这样就可以?

假设你后面用前缀和恢复回 a

a[1] = d[1]
a[2] = d[1] + d[2]
a[3] = d[1] + d[2] + d[3]
...

所以这个差分数组在恢复的时候会自动把 [2, 3, 4] 都加上 10。

来看完整过程:

原数组:       [1, 2, 3, 4, 5]
原差分 d:     [1, 1, 1, 1, 1]
修改 d:       d[2] += 10, d[5] -= 10
更新后 d:     [1, 11, 1, 1, -9]

前缀还原 a:
a[1] = 1
a[2] = 1 + 11 = 12
a[3] = 1 + 11 + 1 = 13
a[4] = 1 + 11 + 1 + 1 = 14
a[5] = 1 + 11 + 1 + 1 - 9 = 5

结果:       [1, 12, 13, 14, 5] ✅