信息学中的差分
差分
差分是一种和前缀和有关的算法
我们来看看差分的定义
令a数组为:1 2 3 1 2 3
那么差分数组b为: 1 1 1 -2 1 1
令a[0] = 0
那么b[i] = a[i] - a[i - 1]
算法解析:
现在要更新数组a的(x1~x2)位:将其增加k
我们可以将b[x1]增加k, 并且将b[x2 + 1]减少k
为什么呢,现在来证明一下算法的正确性:
不妨设n = 10, x1 = 3, x2 = 6
\(\because\Delta a[3] = \Delta a[4] = \Delta a[5] = \Delta a[6] = k\)
\(\therefore\Delta b[4] = \Delta b[5] = \Delta b[6] = 0\)
\(\because[3,6]\)这段区间中所有的数都增加了k
\(\therefore\Delta (a[3] - a[2]) = k, \Delta (a[7] - a[6]) = -k\)
即\(\Delta b[3] = k, \Delta b[7] = -k\)
代码示例:
a[0] = 0;
for(int i = 1; i <= n; i ++) a[i] = read();
for(int i = 1; i <= n; i ++) b[i] = a[i] - a[i - 1];
for(int i = 1; i <= m; i ++) {
int x1 = read(), x2 = read(), k = read();
b[x1] += k, b[x2 + 1] -= k;
}
for(int i = 1; i <= n; i ++)
b[i] += b[i - 1];
for(int i = 1; i <= n; i ++)
cout << b[i] << ' ';
Input:
5 5
1 2 3 4 5
1 3 5
2 2 4
3 5 8
2 3 1
3 4 2
Output:
6 12 19 14 13
口算:
- 6 7 8 4 5
- 6 11 8 4 5
- 6 11 16 12 13
- 6 12 17 12 13
- 6 12 19 14 13
完全正确,可见算法正确性
(看我打那么辛苦就点个赞吧)