📘树状数组(Fenwick Tree)

2026-08-05
⭐⭐⭐ GESP 8级

📖概念讲解

树状数组(Binary Indexed Tree / Fenwick Tree)是一种支持单点修改和前缀和查询的数据结构,两个操作都是 O(log n)。它比线段树代码短得多,常用来处理「频繁更新 + 频繁查询前缀和」的场景。

核心思想:利用二进制的 lowbit(最低位的1)把数组组织成一棵"树"。每个节点管辖一段区间的和,通过不断跳 parent 可以快速求前缀和。

💻代码示例

1#include<iostream>
2using namespace std;
3
4int n, tree[100005]; // tree[] 为树状数组,下标从1开始
5
6// lowbit:取最低位的1,如 lowbit(6)=lowbit(110₂)=2
7int lowbit(int x) { return x & (-x); }
8
9// 单点修改:a[i] 加上 val
10void add(int i, int val) {
11 while (i <= n) { // 往上跳,更新所有管辖区间包含 i 的节点
12 tree[i] += val; // 当前节点累加 val
13 i += lowbit(i); // 跳到 parent 节点
14 }
15}
16
17// 前缀和查询:求 a[1]+a[2]+...+a[i]
18int query(int i) {
19 int sum = 0;
20 while (i > 0) { // 往下跳,累加各段
21 sum += tree[i]; // 累加当前节点管辖的区间和
22 i -= lowbit(i); // 跳到下一个更小的区间
23 }
24 return sum;
25}
26
27int main() {
28 n = 5;
29 int a[] = {0, 3, 1, 4, 1, 5}; // 原始数组,下标从1开始
30 for (int i = 1; i <= n; i++) add(i, a[i]); // 逐个插入建树
31
32 cout << "前缀和[1..3]: " << query(3) << endl; // 3+1+4=8
33 add(3, 2); // a[3] 从4变成6
34 cout << "修改后[1..3]: " << query(3) << endl; // 3+1+6=10
35 cout << "前缀和[1..5]: " << query(5) << endl; // 3+1+6+1+5=16
36}
37// 输出: 前缀和[1..3]: 8 修改后[1..3]: 10 前缀和[1..5]: 16

🧩互动小测

Q1: lowbit(12) 的值是?

Q2: 树状数组 query(5) 会累加哪些 tree[] 节点?

Q3: 单点修改 add(i, v) 的时间复杂度是?

🏋️动手练一练

📝 编程练习

给定一个长度为 n 的数组,支持两种操作:
1. add(i, v):将第 i 个元素增加 v
2. sum(l, r):查询区间 [l, r] 的和

提示:区间和 = query(r) - query(l-1)。用树状数组实现这两个操作。
参考答案:
#include <iostream>
using namespace std;
int n, tree[100005];
int lowbit(int x) { return x & (-x); }
void add(int i, int v) { while (i <= n) { tree[i] += v; i += lowbit(i); } }
int query(int i) { int s = 0; while (i > 0) { s += tree[i]; i -= lowbit(i); } return s; }
int main() {
    n = 5; int a[] = {0, 3, 1, 4, 1, 5};
    for (int i = 1; i <= n; i++) add(i, a[i]);
    cout << query(3) - query(0) << endl;  // sum(1,3) = 8
    add(2, 10);                           // a[2] += 10
    cout << query(5) - query(2) << endl;  // sum(3,5) = 4+1+5=10
}

要点:区间和 = query(r) - query(l-1),这是树状数组的常用技巧。注意 query(0) 返回 0,不用特判。

📝易错点提醒

🏠 返回主页
学完这个知识点后点一下