【引入】
树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个数组的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
这种数据结构(算法)并没有C++和Java的库支持,需要自己手动实现。在Competitive Programming的竞赛中被广泛的使用。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多,实现起来也比较简单。
【原理】
如下图所示,树状数组就是巧妙的进行二进制拆分存储元素之和,从而达到提高求和的效率的目的。
首先,我们先来了解一下lowbit(),这个函数的功能就是求某一个数的二进制表示中最低的一位1.举个栗子,x=6,二进制表示为110,那么lowbit(x)就能返回2。
二进制的视角:一个数n
,假设n = 6
,它的二进制为110
,我们把它表示成累加的形式110 = 100 + 10
,这样是可以的,那么我们要求前6(110)
项的和是不是可以这样求:
∑(i=1,6)=(arr1+arr2+arr3+arr4)+(arr5+arr6)
注意括号中的元素个数,是不是4(100)个加2(010)个,和110=100+10是不是很像,10就是lowbit(110)的结果,100是lowbit(100)的结果。求和的时候我们总是把∑(i=1,n)拆分成这样的几段区间和来计算,而如何去确定这些区间的起点和长度呢?就是根据n的二进制来的,二进制怎么拆的,你