浅见树状数组

☆樱花仙子☆ 提交于 2019-11-28 12:32:12

基本思想

根据任意正整数都可以被关于2的不重复次幂的唯一分解性质,若一个正整数x被分为10101,其中等于1的位是0,2,4,所以x可以被分解为2^4 + 2 ^ 2 + 2 ^ 0,进一步,区间为[1, x]的序列可以分成log(x)个小区间:

1 长度为2 ^ 4的[1, 2 ^ 4];

2长度为2 ^ 2的[2 ^ 4 + 1, 2 ^4 + 2 ^ 2];

3长度为2 ^ 0的[2 ^4 + 2 ^ 2 + 1, 2 ^4 + 2 ^ 2 + 2 ^ 0];

树状数组就是一种基于上述思想的一种数据结构,基本用途就是维护前缀和,将x长的序列分成log(x)个区间,更快

基本算法

由上文可知,若区间结尾为r, 那么区间的长度为r在二进制拆分下最小的2的正整数次幂,我们设为lowbit(r).

对于给定的一个序列a,我们设一个数组c,c[x]保存a的序列[x - lowbit(x) + 1, x]中的所有数的和

下图为树状数组的树形结构

 

该结构满足以下性质::

1 每个节点c[x]保存以他为根的所有子树的所有叶节点的和

2每个节点c[x]的长度为lowbit(x)

3除了树根,每个节点c[x]的父节点就是c[x + lowbit(x)]

4树的深度为log(x)

求lowbit

lowbit(n)表示的是n在二进制下最低的1以及他后面的0构成的数值,那么怎么求呢???

我们来看,一个数的二进制位10001100, 我们可以用他来按位与100,这样我们就可以得到了

首先,我们把它取反,此时数就变成了01110011, 我们将他加1,变成了01110100,这样我们就会发现,我们将n&100 == n&01110100,是不是就可以了?

所以为n&(~n + 1),可不可以在简单一下???

当然可以 在二进制补码下~n  = -1 -n,将他带入我们就得到了-n,所以lowbit(x) = x & -x

 

对某个元素进行加法操作

树状数组支持单点操作,对于单点加法,我们维护的是前缀和,所以我们只要将x及x以后的c数组加上y就可以了!

代码如下:

 

 查询前缀和

树状数组支持查询前缀和,即序列A第1~x数的和。

自己理解吧,时间复杂度为O(logN),代码如下:

统计x-y的值为:sum(y) - sum(x - 1)

拓展

区间修改 区间和查询

代码

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!