树状数组(Binary Indexed Trees,二分索引树),现多用于高效计算数列的前缀和。它可以以O(log n)的时间得到前缀和,并同样以O(log n)对某项加一个常数。
在需要大量计算数列前缀和的时候,我们希望有效利用之前计算过的结果。即,将数列[1-n]的和分成多个部分,每个部分的值是已知的。比如,长度为 7的前缀和,由于 7 = 2^2 + 2^1 + 2^0,如果我们得到了2^2对应的和(a1+a2+a3+a4),2^1对应的和(a5+a6),以及a7,直接相加即可。显然,这个求和的时间复杂度 为O(log n)。
于是,我们需要找一个数组C,它保存了2^n个元素和的信息。编号为奇数的对应当前数,C2、C4、C8...分别代表前2、4、8...个元素的和是显而易见的。对于C6,由于6=4+2,可以表示成C6=a5+a6,
计算[1-6]的和只需计算C6+C4。依次类推。我们定义这样一个函数lowbit(x) = x & (-x),它实现了取出一个正整数的二进制表示的最后一个1对应的数,如 lowbit(111100) = 100。那么,容易得出Cn代表的和对应的区间长度=lowbit(n)。不断令n = n - lowbit(n),就可以找到所有参与计算的Cn。
对于更新操作,如a5的更新,就需要改变C5、C6、C8的值。相当于是上述过程的逆过程。
转自http://www.yuyii.com/2013/10/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84-poj-stars/
参考:https://zh.wikipedia.org/zh-cn/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84#.E6.B1.82.E5.92.8C