树状数组是一种形如大树的数据结构。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组超快,代码简洁,内存超少,几乎没缺点。
可以发现:
C[1] =a[1] ------------------------------C[1B]管1个
C[2] =a[1]+a[2]--------------------------C[10B]管2个
C[3] =a[3]-------------------------------C[11B]管1个
C[4] =a[1]+a[2]+a[3]+a[4]----------------C[100B]管4个
C[5] =a[5]-------------------------------C[101B]管1个
C[6] =a[5]+a[6]--------------------------C[110B]管2个
C[7] =a[7]-------------------------------C[111B]管1个
C[8] =a[1]+a[2]+…+a[8]------------------C[1000B]管8个
..............................
C[16]=a[1]+a[2]+…+a[16] ---------------C[10000B]管16个
这里有一个有趣的性质:如果C[x],x转为二进制,后面有连续k个0,那么C[x]管2^k 个,
而且分别是 a[x]+a[x-1]+a[x-2]+ … +a[x–2^k+1]。
想要得到c[x]的管理区域非常简单,只需要 x&-x 即可,这是利用了计算机是以补码的形式存储数字的特性,使之一步到位,简单便捷。
知道了c[x]的管理范围和它的编号后,我们就可以求出:
1、离c[x]最近并且管理c[x]的管理者,它是x+lowbit(x) ;
2、在c[x]之前并且恰好不管理c[x]的管理者,它是x-lowbit(x)。
推荐:《树状数组—改点求段》http://blog.csdn.net/a_bright_ch/article/details/54598319
《树状数组—改段求段》http://blog.csdn.net/a_bright_ch/article/details/54616312
《树状数组—改段求点》http://blog.csdn.net/a_bright_ch/article/details/54616490