差分序列
本文将介绍差分序列的定义及其应用。
差分序列(数组)
差分序列的定义
给定一个序列 a, a[i] 表示序列的第 i 个元素(编号从 0 开始),则其差分序列为:
1 | d[0] = a[0] (i == 0) |
差分序列示例
索引 i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
原始序列 a[i] | 0 | 2 | 5 | 4 | 9 | 7 | 10 | 0 |
差分序列 d[i] | 0 | 2 | 3 | -1 | 5 | -2 | 3 | -10 |
现在假设将区间 a[1, 4] 所有的数都加上 3,则:
索引 i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
原始序列 a[i] | 0 | 2+3=5 | 5+3=8 | 4+3=7 | 9+3=12 | 7 | 10 | 0 |
差分序列 d[i] | 0 | 2+3=5 | 3 | -1 | 5 | -2-3=-5 | 3 | -10 |
然后将区间 a[3, 5] 所有的数都减去 5,则:
索引 i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
原始序列 a[i] | 0 | 2+3=5 | 5+3=8 | 4+3=7-5=2 | 9+3=12-5=7 | 7-5=2 | 10 | 0 |
差分序列 d[i] | 0 | 2+3=5 | 3 | -1-5=-6 | 5 | -2-3=-5 | 3+5=8 | -10 |
差分序列的性质
仔细观察上面的示例,可以发现:
1 | a[2] = d[2] + a[1] |
根据定义,对原序列区间操作后,原序列最终各项值为:
1 | a[0] = d[0] (i == 0) |
也即 a[i] 为 d[i] 的前缀和:
1 | a[i] = d[0] + ... + d[i] |
差分序列的应用
基于差分序列的性质,它主要用于快速处理区间加减操作和单点查询
快速处理区间加减操作
假如现在对 a[L, R] 区间上所有的数加上 delta,由以上的性质可知,第一个受影响的差分数组中的元素为 d[L],即令 d[L] += delta,那么后面数列元素在计算过程中都会加上 delta;最后一个受影响的差分数组中的元素为d[R],所以令 d[R+1] -= delta,即可保证不会影响到 R 以后数列元素的计算。这样我们不必对区间内每一个数进行处理,只需处理两个差分后的数即可。
简单来说,当对 a[L, R] 区间所有数进行加 delta 操作时,只需:
1 | d[L] += delta |
那么此时计算 a[L] ... a[R] 都会加上 delta,这里用 (d[L] + delta) 表示归约后的 d[L],则有:
1 | a[L] = (d[L] + delta) + a[L-1] |
单点查询(求差分序列前缀和)
改变 d 数组
1 | for i in range(1, n): |
改变 a 数组
1 | a[0] = d[0] |