差分

差分与前缀和互为逆运算。

一维差分

一维差分用来将子数组每个元素加上c,可以将复杂度由$O(n)$降为$O(1)$。

原数组a、差分数组d必须在前部有0边界,即a[0] = 0s[0] = 0

a[1...n]d[1...n]存储数据。

void add(int l, int r, int c) {
    d[l] += c;
    d[r+1] -= c;
}

for (int i = 1; i <= n; i++) add(i, i, a[i]);

add(l, r, c);

for (int i = 1; i <= n; i++) d[i] += d[i-1];

二维差分

二维差分用来将子矩阵每个元素加上c,可以将复杂度由$O(n*m)$降为$O(1)$。

原矩阵a、差分矩阵d必须在前部有0边界,即a[0][0...n] = a[0...n][0] = 0d[0][0...n] = d[0...n][0] = 0

a[1…n][1…n]、d[1…n][1…n]存储数据。

void add(int x1, int y1, int x2, int y2, int c) {
    d[x1][y1] += c;
    d[x2+1][y1] -= c;
    d[x1][y2+1] -= c;
    d[x2+1][y2+1] += c;
}

for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        add(i, j, i, j, a[i][j]);

add(x1, y1, x2, y2, c);

for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        d[i][j] += d[i-1][j] + d[i][j-1] - d[i-1][j-1];