差分算法总结
差分是前缀和的逆运算
一维差分
对于a1,a2,…,an,构造b1,b2,…,bn,使得ai = b1 + b2 + … + bi。此时,b数组成为a数组的差分,a数组称为b数组的前缀和。
题目链接:
https://www.acwing.com/problem/content/799/
代码模版:
#include <iostream> using namespace std; const int N = 100010; int n, m, x; int b[N]; void insert(int l, int r, int c) { b[l] += c; b[r + 1] -= c; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &x); insert(i, i, x); } while (m--) { int l, r, c; scanf("%d%d%d", &l, &r, &c); insert(l, r, c); } for (int i = 1; i <= n; i++) { b[i] += b[i - 1]; printf("%d ", b[i]); } return 0; }
二维差分
原矩阵为A = (aij)n*m,差分矩阵为B = (bij)n*m,使得矩阵A是差分矩阵B的前缀和。
初始化:令矩阵A = O,那么矩阵B = O。然后把矩阵A中的每个元素依次插入。
题目链接:
https://www.acwing.com/problem/content/800/
代码模版:
#include <iostream> using namespace std; const int N = 1010; int n, m, q, x; int b[N][N]; void insert(int x1, int y1, int x2, int y2, int c) { b[x1][y1] += c; b[x2 + 1][y1] -= c; b[x1][y2 + 1] -= c; b[x2 + 1][y2 + 1] += c; } int main() { scanf("%d%d%d", &n, &m, &q); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &x); insert(i, j, i, j, x); } while (q--) { int x1, y1, x2, y2, c; scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c); insert(x1, y1, x2, y2, c); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; printf("%d ", b[i][j]); } puts(""); } return 0; }