concept
Tree-like array or binary index tree is also called Binary Indexed Tree, also known as Fenwick tree; its query and modification time complexity is the same log(n)
, and the space complexity O(n)
is tree-like structure for skip scanning. Often used to efficiently compute prefix sums and range sums of sequences.
The a array is the original array, and the c array is a tree array. It can be found that
C1 = A1
C2 = A1+A2
C3 = A3
C4 = A1+A2+A3+A4
C5 = A5
C6 = A5+A6
C7 = A7
C8 = A1+A2+A3+A4+A5+A6+A7+A8
principle
lowbit
It formulates k, where k is the number of zeros from the end of the value. Then add the result obtained by x itself to obtain the position of the parent node of the current node, or subtract the result from x to obtain the position of the previous parent node. For example, the current is 6, the binary is 0110, and k is 2, then 6+2=8, and C(8) is the position of the parent node of C(6); on the contrary, 6-2=4, it is C(6 )'s position of the previous parent node.
int lowbit(int x) { return (x & (-x)); }
Note: lowbit cannot handle the case of 0, because its result is also 0, then it is an infinite loop in the end, so all tree arrays are set to subscripts starting with 1
single point modification
When we want to update the bottommost value, the sum stored by its corresponding parent node also needs to be updated, so the modified code is as follows:
// Modify the value of a point backward void add( int x, int d) { while(x <= n) { a[x] += d; x += lowbit(x); } }
Inquire
When querying, you need to count forward
// Forward count the interval of [1, x] and int sum( int x) { int ret = 0; while(x > 0) { ret += a[x]; x -= lowbit(x); } return ret; }
Notice:
Update a point a[i] += p; call add(i, p);
To find the sum of the interval [x, y] call sum(y) – sum(x - 1);
15=(1111)2, through lowbit decomposition, it can become the sum of 4 numbers:(1111)2=(1)2+(10)2+(100)2+(1000)2, and then we analyze the process of jumping backwards.Subtract 15 to the smallest power of 2, 2^0 to get 14.Subtract 14 to the smallest power of 2, 2^1 to get 12.Subtract 12 to the smallest power of 2, 2^2 to get 8.Subtract 8 to the smallest power of 2, 2^3 to get 0.
So C(15) = C(14) + C(12) + C(8) + C(0), as can be seen from the figure, the result is correct.
除此之外,树状数组能够快速的求任意区间的和,设sum(k) = A[1] + A[2] + ... + A[k],则A[i] + A[i+1] + ... + A[j] = sum(j) - sum(i-1)。
树状数组还有区间修改单点求和的作用
1 int sum(int x) 2 { 3 int ret = 0; 4 while(x <= n) 5 { 6 ret += a[x]; 7 x += lowbit(x); 8 } 9 return ret; 10 } 11 //向前修改[0, x]整个区间加上d 12 void add(int x, int d) 13 { 14 while(x > 0) 15 { 16 a[x] += d; 17 x -= lowbit(x); 18 } 19 } 20 更新某区间,使区间[x, y]加上d调用add(y, d);add(x-1, -d); 21 求a[x],调用sum(x);