树状数组
看了很多写树状数组的,感觉各有优缺点,索性就按照自己的理解顺序梳理一下。
简介
树状数组(Binary Indexed Tree, Fenwick Tree),是一种用于高效处理对一个存储数字的列表进行更新及求前缀和、区间和的数据结构。
什么是前缀和以及区间和?前缀和是一个数组的某项下标之前(包括此项元素)的所有数组元素的和。 区间和就是给定区间的数组的和。
它的查询和修改的时间复杂度都是log(n),空间复杂度则为O(n)。这正是使用树状数组的原因。
(碰到更新元素、求前缀和、区间和就可以考虑树状数组)。
举例理解
首先我们很关心一个普通数组是怎么变成树状数组的。
先看上图(最上面一行为A数组也就是原始数组,最下面一行为C数组,改变之后的树状数组)可以看出:
1=(001) C[1]=A[1];
2=(010) C[2]=A[1]+A[2];
3=(011) C[3]=A[3];
4=(100) C[4]=A[1]+A[2]+A[3]+A[4];
5=(101) C[5]=A[5];
6=(110) C[6]=A[5]+A[6];
7=(111) C[7]=A[7];
8=(1000) C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
…
接下来引入lowbit:我们主要是求一个数字的二进制表示的1所在的最低位(k),而lowbit=2^k。
举例:
十进制 | 二进制 | lowbit |
---|---|---|
2 | 0010 |