浅见树状数组

Posted -sheldon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅见树状数组相关的知识,希望对你有一定的参考价值。

基本思想

根据任意正整数都可以被关于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)

拓展

区间修改 区间和查询

技术图片

代码

技术图片

 

以上是关于浅见树状数组的主要内容,如果未能解决你的问题,请参考以下文章

树状数组和线段树有啥区别?

树状数组的树状数组的经典操作

树状数组模板

数据结构之树状数组从零认识树状数组

树状数组 / 二维树状数组

浅谈树状数组