Fenwick Tree (树状数组) 模板详解

Fenwick Tree (树状数组) 模板详解
靖Fenwick Tree (树状数组) 模板详解
1. 简介
树状数组(Fenwick Tree 或 Binary Indexed Tree,简称 BIT)是一种支持单点修改和区间查询的数据结构。它的主要特点是:
- 实现简单,代码量小
- 时间复杂度为 O(log n)
- 空间复杂度为 O(n)
- 支持动态维护前缀和
2. 实现原理
2.1 基本概念
树状数组巧妙地利用了整数的二进制表示,通过 lowbit
运算(x & -x
)来维护数组的前缀和信息。每个节点存储的是原始数组中一段区间的和。
2.2 核心操作
- 单点修改:更新一个位置的值,同时维护其影响的所有区间
- 前缀和查询:查询从开始到指定位置的元素和
- 区间查询:通过两次前缀和查询的差值得到
- 二分查找:查找第一个使前缀和大于给定值的位置
3. 模板代码
1 | template <typename T> |
4. 函数说明
4.1 构造函数和初始化
1 | Fenwick(int n_ = 0) |
- 支持默认构造和指定大小构造
init
函数初始化大小为 n 的树状数组- 所有元素初始化为类型 T 的默认值
4.2 单点修改
1 | void add(int x, const T &v) |
- 将位置 x 的值增加 v
- 时间复杂度:O(log n)
- x 的范围是 [0, n-1]
4.3 前缀和查询
1 | T sum(int x) |
- 计算区间 [0, x) 的元素和
- 时间复杂度:O(log n)
- x 的范围是 [0, n]
4.4 区间查询
1 | T rangeSum(int l, int r) |
- 计算区间 [l, r) 的元素和
- 通过两次前缀和查询实现
- 时间复杂度:O(log n)
4.5 二分查找
1 | int select(const T &k) |
- 查找第一个使前缀和大于 k 的位置
- 时间复杂度:O(log n)
- 返回值范围是 [0, n]
5. 时间复杂度分析
- 初始化:O(n)
- 单点修改:O(log n)
- 前缀和查询:O(log n)
- 区间查询:O(log n)
- 二分查找:O(log n)
6. 应用场景
- 动态维护前缀和
- 区间查询问题
- 统计逆序对
- 动态维护排名
- 区间更新(差分)
7. 注意事项
- 下标从 0 开始,内部实现时需要注意 +1 和 -1 的转换
- 模板支持任意类型 T,但要求 T 支持加法运算和默认构造
- 区间查询返回的是左闭右开区间 [l, r) 的结果
- 二分查找函数在所有前缀和都不大于 k 时返回 n
8. 优化技巧
- 使用位运算
i & -i
计算 lowbit - 区间查询使用两次前缀和的差值
- 二分查找时使用位运算优化
- 可以扩展支持区间修改(差分)
9. 总结
树状数组是一种非常实用的数据结构,它在处理动态区间查询问题时表现优秀。相比线段树,它的代码更简洁,常数更小,但功能相对较少。在实际应用中,如果只需要支持单点修改和区间查询,树状数组是一个很好的选择。
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果