核心概述:树状数组(Fenwick Tree)支持单点增量更新与前缀和查询,含按和找位置的 lower_bound,所有操作均为 O(log N)。

原文引述:

Description: Computes partial sums a[0] + a[1] + … + a[pos - 1], and updates single elements a[i], taking the difference between the old and new value. Time: Both operations are . Status: Stress-tested

展开阐述:

  • 定义与问题背景、适用场景
    • 用于维护一维数组的前缀和,支持频繁的点更新与区间前缀查询,在在线计数、秩统计、离散化后的频率统计等场景广泛适用。
  • 接口与数据结构字段
    • 内部:一维数组 s 存每个低位块的累加值,基于二进制最低位分块思想。
    • update(pos, dif):将 a[pos] 增加 dif(传入“差值”,非直接赋值)。
    • query(pos):返回前缀和 sum([0, pos)),半开区间。
    • lower_bound(sum):返回最小的 pos 使前缀和 ≥ sum;sum ≤ 0 返回 -1;若从未达到则返回 n。
  • 核心算法流程/要点
    • update:for (; pos < sz(s); pos |= pos + 1) s[pos] += dif
      • 利用 pos |= pos + 1 跳至包含该点的更大块,逐层累加。
    • query:for (; pos > 0; pos &= pos - 1) res += s[pos - 1]
      • 逐步去掉最低位 1,累加覆盖块得到前缀和。
    • lower_bound:二进制提升,按 2^k 从高到低试探扩展,当试扩后块和仍小于目标时推进并减少目标值。
  • 复杂度与边界条件
    • 三个操作均为 O(log N);数组下标多为 0 基或 1 基的实现细节需统一,本文以 query([0,pos))为约定。
    • lower_bound 的返回值约定需遵守,以免与业务下标语义冲突。
  • 实现细节与坑
    • update 使用差值语义,若需“赋值”为 x,应先求 dif = x - 当前值。
    • query 是半开区间 [0,pos),避免 off-by-one。
    • lower_bound 需要预先确定最大的探测步长(不小于 n 的最大 2 的幂)。
  • 变体/扩展
  • 正确性要点
    • 依赖二进制分块不变式:s[i] 存储覆盖 [i - lowbit(i) + 1 .. i] 的和(按实现的下标约定适配),update/query 分别沿着块父链累加/剥离,保证前缀和一致。

关联节点