前缀和与差分动画演示

一次累加换 O(1) 区间和;区间批量加法则反过来用差分。

键盘:← → 单步 ·空格 播放/暂停 · R 重置 ·Home/End 到两端

前缀和把「任意区间的和」变成两次取数一次减法:S[i] 记前 i 个元素之和,a[l..r] 的和就是 S[r+1] 减 S[l]。舞台上面两排格子上下对齐,原数组每建一格,S 就多填一格;S 比原数组长出来的那一格是 0 占位,它让左端为 0 的区间不用特判,也让「前 i 个」这个说法在 i = 0 时有意义。第三排格子是差分数组,逐格由相邻两项相减得到。

差分是前缀和的逆运算,用法也正好相反:想把区间 [l, r] 整体加 v,不去逐个改元素,只在 d[l] 加 v、在 d[r+1] 减 v,全部操作做完再从头累加一次还原。批量区间加很多次的场景里,写入次数从「区间长度之和」降到「操作数的两倍」。还原阶段原数组那一格会留着加了多少的次级说明,可以直接对着看每一位的来路。

前缀和与差分演示怎么用

  • 换题面:区间和查询那档逐格建 S 再做三次查询;差分数组那档先建 d,再连做几次区间加,最后一次性还原。
  • 盯住占位格:第 0 格单独有一步解释为什么是 1 位数 0:没有它,S[r+1] - S[l] 的写法要在左端为 0 时开小灶。
  • 改数据:自定义栏填数字(空格或逗号分隔,上限 12 个),查询区间会按数组长度自动挪位置,还原结果照样能对上暴力解。
  • 看两个数组对齐:S 的下标比 a 右移一格,d 的下标和 a 对齐。三排格子并排放,就是为了让你能一眼看出谁多了一格。

常见问题

为什么 S 要多一个 0 占位?

因为「区间和」要减的是 l 左边的和。a[l..r] 里有 r-l+1 个数,左边那段是 a[0..l-1],它正好是 S[l]。如果 S[i] 定义成「含 a[i] 的前缀」,那 l = 0 时没有左边,得写 if 特判,而且 S[r] - S[l] 会把 a[l] 多减掉或漏掉。多一格 0 之后,所有区间都同一条公式,边界不再特殊。

S[r] - S[l] 和 S[r+1] - S[l] 到底差在哪?

差一个 a[r]。前者算的是 a[l+1..r](少算左端、多算右端那种错位),后者才是 a[l..r]。这一格偏移是前缀和里出镜率最高的错误,写之前先问自己一句:S 的下标指的是「几个数」。

差分数组为什么只改两个点?

d 是相邻两项之差,把 d[l] 加上 v 之后,从 l 往后逐格还原时每一位都会带上这个 v;而区间只到 r,所以在 r+1 处再减掉 v,让 v 的作用范围正好在 [l, r] 内截住。漏掉 r+1 那一笔,r 之后的所有位置都会被连累多加一次;r 是最后一格时 r+1 越界,要判掉。

前缀和还能配哈希表做什么?

把「区间和等于 k」改写成「S[r] - S[l] = k」,于是扫到 r 时只需要查前面有没有 S 值等于 S[r] - k,用哈希表记每个前缀出现过的次数,一次遍历就能数出满足条件的子数组个数,还能兼容负数。这类题的共通点都是:先算前缀,再把区间条件换成两点的关系。

演示编号 D04无需安装,手机端同样可用按 Ctrl + K 搜工具与演示

顺手能用上的工具