tree array

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);

 

 

E.g

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);

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324711655&siteId=291194637
Recommended