树状数组简单易懂的详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

树状数组简单易懂的详解
1 什么是树状数组
树状数组(Fenwick Tree),也叫做树形数组,是一种支持单点
修改、区间查询的数据结构。

这种数据结构可以在O(log n)的时间复
杂度内实现单点修改和区间查询,相较于线段树,树状数组实现较为
简单。

2 树状数组的实现原理
树状数组的核心思想是利用二进制中的位运算来维护前缀区间和。

假设有一个数组a[],其前缀和为sum[],那么对于每个下标i,只需
要维护[1,i]这个区间的和,即sum[i]。

这样,当需要查询区间[1,r]
的和时,只需要计算sum[r]即可,不需要遍历每一个元素。

对于单点修改操作,假设我们要将数组a[]的第i个元素修改为x,我们只需要将第i个元素的值改为x,并且要将[1,i]这个区间内所有
的sum数组的值都加上x-a[i],即将差值x-a[i]加到了[1,i]区间中。

3 树状数组的实现细节
3.1 树状数组的初始化
树状数组需要初始化为0,因为我们需要维护的是每个元素的前缀和,如果没有初始化为0,其前缀和也就变得不可预测了。

查询区间[1,r]的和时,只需要计算sum[r]即可。

具体实现过程为:从r开始向前跳,每一个位置的前缀和都加到一个答案变量ans中,
直到跳到0为止。

可以使用以下的代码实现:
```C++
int query(int x)
{
int ans = 0;
while(x > 0)
{
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
```
修改操作也很简单,只需要将第i个位置的值改为x,然后将[1,i]这个区间内所有的sum数组的值都加上x-a[i],即将差值x-a[i]加到了[1,i]区间中,可以使用以下的代码实现:
```C++
void update(int x, int val)
{
while(x <= n)
{
tree[x] += val;
x += lowbit(x);
}
}
```
4 树状数组与线段树的比较
相对于线段树,树状数组的实现更为简单,而且更加省空间。

但是,树状数组的应用场景相对要更加有限,只适用于支持区间修改,
单点查询的场景,而线段树更加灵活,可以处理更多的情况。

5 总结
树状数组是一种支持单点修改、区间查询的数据结构,其核心思想是利用二进制中的位运算来维护前缀区间和。

在实现时需要注意进行初始化,并且维护前缀的值是当前元素及其之前的所有元素的和。

相对于线段树,树状数组更加简单,实现起来更加方便。

相关文档
最新文档