差分
791 字
4 分钟
差分

差分
差分可以看作前缀和的反向操作。前缀和擅长快速查询区间和,差分擅长快速做区间修改。
如果题目经常出现:
把区间 [l, r] 中每个数都加上 c那么差分就是很适合的工具。
1、一维差分的思想
假设原数组是 a,差分数组是 b:
b[1] = a[1]b[2] = a[2] - a[1]b[3] = a[3] - a[2]...那么对 b 求前缀和,就能还原 a:
a[i] = b[1] + b[2] + ... + b[i]2、为什么区间加能变成 O(1)
如果想让 [l, r] 都加上 c,只需要:
b[l] += cb[r + 1] -= c原因是:
- 从
l开始,前缀和都会多加c。 - 到
r + 1时,再减掉c,让后面的数恢复原样。
3、一维差分模板
#include <bits/stdc++.h>using namespace std;
const int N = 100010;
int n, m;int a[N], 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", &a[i]);
for (int i = 1; i <= n; i++) { insert(i, i, a[i]); }
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;}4、二维差分解决什么问题
二维差分对应的是矩阵里的子矩形修改:
把左上角 (x1, y1) 到右下角 (x2, y2) 的所有元素都加上 c如果直接遍历子矩形,复杂度可能很高。二维差分可以把一次矩形修改变成 O(1)。
5、二维差分公式
对子矩形加 c:
b[x1][y1] += cb[x2 + 1][y1] -= cb[x1][y2 + 1] -= cb[x2 + 1][y2 + 1] += c最后对差分矩阵做二维前缀和,就能得到修改后的原矩阵。
6、二维差分模板
#include <bits/stdc++.h>using namespace std;
const int N = 1010;
int n, m, q;int a[N][N], 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", &a[i][j]); insert(i, j, i, j, a[i][j]); } }
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]); } printf("\n"); }
return 0;}7、差分和前缀和的关系
可以这样理解:
差分数组 --做前缀和--> 原数组原数组 --相邻项相减--> 差分数组所以差分最后一定要“还原”,也就是做一次前缀和。
8、容易写错的地方
(1)一维区间右端要写 r + 1
b[r + 1] -= c;这是让影响在 r 后面停止。
(2)二维右下角是 x2 + 1, y2 + 1
b[x2 + 1][y2 + 1] += c;不要写成 b[x2][y2] += c。
(3)还原二维矩阵时列数用 m
for (int j = 1; j <= m; j++)不要把列循环写成 j <= n。
总结
差分适合“多次区间修改,最后一次性输出结果”的问题。
一维:b[l] += c, b[r + 1] -= c二维:四个角做加减文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














