差分
快速处理区间加减(前缀和的逆运算)
for(int i=n-1;i>=0;i--) |
1 1 1 1 1 1 1 1
前缀和得到 差分得到
1 2 3 4 1 0 0 0
差分得到 前缀和得到
1 1 1 1 恢复为原数组 1 1 1 1 恢复为原数组
和前缀和互为逆运算:
前缀和数组做差分:
- ($i$ 位置的前缀和是 $0$ 到 $i$ 的总和)
- ($i-1$ 位置的前缀和是 $0$ 到 $i-1$ 的总和)
- 相减得出:
- 这意味着:前缀和数组的差分(相邻项相减)就是原数组的元素。
差分数组计算前缀和:
- … (中间省略)
- 左边相加:
这实际上就是在对差分数组 $d$ 求前缀和。
$a[l, r] + k \Longleftrightarrow d[l] + k, \quad d[r+1] - k$
如果你想给原数组 $a$ 的区间 $[l, r]$ 内的所有数字都加上 $k$,你只需要在差分数组 $d$ 的左边界 $l$ 处加上 $k$,并在右边界的下一个位置 $r+1$ 处减去 $k$。

二维差分
先对每一列差分,再对每一行差分
异或差分

第一步:构造异或差分数组
将原数组转化为一个“异或差分”序列。
- 计算规则: 差分数组 $d[i] = a[i] \oplus a[i-1]$(规定 $a[0] = 0$)。
- 图片示例: 原数组
[1, 2, 3, 4, 5, 6]经过“差分”后变为[1, 3, 1, 7, 1, 3]。 - 操作公式:
- $d[l] = d[l] \oplus k$
- $d[r+1] = d[r+1] \oplus k$
- 图片示例: 对区间 $[2, 5]$ 执行
^ 2(异或 2)。 - 计算公式: $a’[i] = d[1] \oplus d[2] \oplus \dots \oplus d[i]$。
- 图片示例: 对
[1, 1, 1, 7, 1, 1]求前缀异或和。- 第 1 位:$1$
- 第 2 位:$1 \oplus 1 = 0$
- 第 3 位:$0 \oplus 1 = 1$
- 第 4 位:$1 \oplus 7 = 6$
- 第 5 位:$6 \oplus 1 = 7$
- 第 6 位:$7 \oplus 1 = 6$
- 最终数组:
[1, 0, 1, 6, 7, 6]。
对于区间 $[l, r]$ 进行异或 $k$ 的操作,其差分逻辑为:
利用多重差分来解决多项式形式的区间修改

1. 核心概念:差分与导数的关系
在离散数学中,差分(Difference)之于数列,就相当于导数(Derivative)之于连续函数。
- 常数的导数是 0。
- $x$(一次函数)的导数是常数。
- $x^2$(二次函数)的导数是一次函数。
差分也是同理:
每一次差分操作,都会把多项式的最高次幂降低 1 次。2. 图片公式逐行详解
图片中列举了不同复杂度的修改($add_x$),以及它们对应的处理方式。第一行:$add_x = a$ (常数修改)
- 含义:这是最基础的区间修改。比如“给区间 $[L, R]$ 的每个数都加上常数 $a$”。
- 多项式次数:$0$ 次(因为 $a = a \cdot x^0$)。
- 所需差分阶数:一阶差分。
- 原理:
常数序列(如 $3, 3, 3, 3$)做一次差分后,中间全是 $0$(除了边界)。 - 含义:给区间加上一个等差数列。比如“给第 $x$ 个数加上 $2x+1$”。
- 多项式次数:$1$ 次。
- 所需差分阶数:二阶差分。
- 原理:
- 含义:给区间加上一个平方级别的增长量。比如“物理中的匀加速运动位移”。
- 多项式次数:$2$ 次。
- 所需差分阶数:三阶差分。
原理:
- 降维打击:利用差分性质,把复杂的曲线(高次多项式)通过多次差分“打平”成 0。
- 操作:
- 如果你要加一个 $k$ 次多项式。
- 你就建立一个 $k+1$ 阶差分数组。
- 你只需要在这个高阶差分数组的 $L$(起点) 和 $R$(终点) 附近修改少数几个值。
- 还原:
- 当询问最终结果时,对这个 $k+1$ 阶差分数组做 $k+1$ 次前缀和(Prefix Sum),就能还原出原始数组的增量。
差分的正负性反应了原数组的增减性

1. 核心逻辑:从“面”到“点”的降维
- 左边(原数组视角):
- 操作:
任选 [L, R],让区间内所有元素加 1 或减 1。 - 难点:每次操作涉及很多个数,状态难以穷举。
- 目标:想让原数组变成递增、递减或者所有数相等。
- 操作:
- 右边(差分数组视角):
- 操作:由于差分的性质($D[L]+v, D[R+1]-v$),原数组的一次区间修改,等价于在差分数组中任选两个位置,一个加 1,一个减 1。
- _特殊情况_:如果只选一个位置修改(比如只改 $L$ 处),其实是因为另一个位置选在了 $N+1$(越界无效位置),图中的
X | 1 2 3 4 | X就在暗示这种边界处理。
- _特殊情况_:如果只选一个位置修改(比如只改 $L$ 处),其实是因为另一个位置选在了 $N+1$(越界无效位置),图中的
- 优势:操作从“修改一排数”变成了“修改两个数”,复杂度大大降低。
- 目标:
- 原数组递增 $\Longleftrightarrow$ 差分数组每一项(除第一项外)都 $\ge 0$。
- 原数组递减 $\Longleftrightarrow$ 差分数组每一项(除第一项外)都 $\le 0$。
- 原数组相等 $\Longleftrightarrow$ 差分数组每一项(除第一项外)都 $= 0$。
2. 经典案例解析:IncDec Sequence
这张图其实对应了一道非常经典的算法题(NOIp 2011 提高组《IncDec Sequence》)。
问题描述
给定一个数组,每次可以选择一个区间 $[L, R]$ 进行 $+1$ 或 $-1$ 操作。问最少操作多少次,能让数组中所有元素都相等?
结合这张图的解法:
- 操作:由于差分的性质($D[L]+v, D[R+1]-v$),原数组的一次区间修改,等价于在差分数组中任选两个位置,一个加 1,一个减 1。
- 转化目标:
让“原数组所有元素相等”,等价于让“差分数组 $D[2], D[3] \dots D[n]$ 全部变为 0”。(注意 $D[1]$ 不需要为 0,因为 $D[1]$ 决定了最终相等的那个数值是多少)。 - 分析现状:
计算出初始的差分数组后,你会发现 $D[2 \dots n]$ 中有一些正数(需要减),有一些负数(需要加)。 - 匹配操作(图中的“任选两个位置”):
- 贪心策略 1:优先在 $D[2 \dots n]$ 内部找一正一负进行配对。比如 $D[i] > 0, D[j] < 0$,我们就对区间 $[i, j-1]$ 操作。这样能一次性解决两个数的偏差(“一个加,一个减”),效率最高。
- 贪心策略 2:如果正负无法配对(比如只剩下正数了),那就只能和边界($D[1]$ 或 $D[n+1]$)配对。这对应图中“任选一个位置,增加/减少”。
- 结论:
通过把复杂的区间问题转化为差分数组上的正负数抵消游戏,我们可以瞬间得出最少操作次数公式:$\max(\text{正数和}, |\text{负数和}|)$。3. 总结
这张图想表达的是差分技术的最高境界:
不仅仅是用它来快速修改数据(如前两张图所述),而是用它来重构问题的定义。
- 看到“区间加减” $\rightarrow$ 转化为 “差分数组的两点修改”。
- 看到“单调性/相等”目标 $\rightarrow$ 转化为 “差分数组的正负/零”目标。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Zedward'Blog!
评论
