[Data Structure and Algorithm] Tree Array

Fenwick Tree


Binary Indexed Tree (also known as Fenwick Tree) is an array-based data structure for efficient and dynamic maintenance of prefix sums.

Tree arrays can be done in O ( log ⁡ n ) O(\log n)O(logThe single-point modificationandprefix summationwithin the time complexity of n ) is suitable for some problems that only need to maintain the prefix sum, such as interval summation, interval mean, interval median, etc.

1. Problem description

For a given array a 1 , a 2 , . . . , a [ n ] a_{1},a_{2},...,a[n]a1,a2,...,a [ n ] , when you need to frequently ask a certain intervalai , ai + 1 , . . . , a [ j ] a_{i},a_{i+1},...,a[j]ai,ai+1,...,a[j] (其中 1 < = i < j < = n 1<=i<j<=n 1<=i<j<=n ), and there exists modificationai a_{i}aiIn the case of element values, how to design an efficient query and modification algorithm?

An intuitive approach is the brute force method, which is O ( 1 ) O(1) each timeThe time complexity of O ( 1 ) is modified at a single point, but in the process of query, because each element in the interval needs to be traversed, the worst case requiresO ( n 2 ) O(n^{2})O ( n2 )time (here it is assumed that the size of the operation isO ( n ) O(n)O ( n ) ). In order to solve this low query efficiency, one idea is to use a tree array.

2. Solve ideas

In the tree array ddIn d , the value stored in each array position is not only the value of the current element, but the cumulative value of the elements in a certain interval. The specific storage rules are shown in the left diagram of the figure below.

insert image description here

In the diagram on the left, the matrix corresponding to the subscript of the element indicates the value stored at the location 矩阵覆盖区域对应的原数组元素之和, for example, the subscript is 1 11 place stores the element value of the original array subscript 1, and the subscript 4 stores the original array subscript1 11 to4 4The sum of the element values ​​of 4 .

The storage rule reflected in the storage graph of the tree array is:

The number is xxThe interval governed by the nodes of x is 2 k 2^{k}2k (wherekkk forxxThe number of zeros at the end of binary x ) elements.

For example d[6] = a[5] + a[6] d[6] = a[5] + a[6]d[6]=a[5]+a [ 6 ] , because the binary number corresponding to position 6 is110, the number of zeros at the end is 1, so it needs to store2 1 = 2 2^{1} = 221=2 elements, the same applies to others.

With the above storage rules, how to perform range query and element modification operations? In order to facilitate the description of the operation, the diagram on the left can be rotated to obtain the diagram on the right (the depth of the tree is log 2 n + 1 log_{2}{n+1}log2n+1 ), and use a straight line to represent the relationship between the prefix accumulation nodes. In addition, in order to facilitate the subsequent description of range query and element modification operations, lowbitthe operation

public int lowbit(int x) {
    
    
    return x & (-x);
}

The so-called lowbitoperation is to obtain the current variable xxx The position of the last 1 in the binary. This operation can be remembered first, and the subsequent operation introduction can help further understanding.

(1) Interval query

In the tree structure shown on the right, if you query the prefix sum of a certain node, you need to find the previous node from this point to the left, and add the value of its node, so as to continuously search and accumulate the node value to the left. For example, to query the prefix sum 节点 7of , you need to 节点7start from , find 节点 6for the accumulation operation, and then find 节点 4for the accumulation operation (it can be understood in combination with the coverage area of ​​the matrix in the figure). So how is this traversal process achieved? This requires us to convert the node number into binary form first:

  • 7 ---- 0111
  • 6 ---- 0110
  • 4 ---- 0100

A general rule can be found: the position of the next traversal x ′ x'x' is the current positionxxx erases the last 1on the binary bit1 . Therefore, lowbitthe operationx ′ x’x 有: x ′ = x − l o w b i t ( x ) x' = x - lowbit(x) x=xlowbit(x)

(2) Element modification

Element modification can be regarded as the reverse process of interval query, that is, in the tree structure shown on the right, if one of the nodes is modified, it is necessary to find the parent node layer by layer (to the upper right, which is exactly the same as the interval query instead), and apply the same modification process to each parent node as needed. For example 节点 3, add kk tok operation, you need to traverse节点 3,节点 4,kk节点 8in the process of traversalk operation. In the process of traversing the next node, you only need to use the reverse process similar to the interval query, that is, for the currentxxx position node, the next traverse nodex ′ = x + lowbit ( x ) x' = x+lowbit(x)x=x+lowbit(x)

3. Code implementation

class FenwickTree {
    
    
    private int[] tree;
    
    public FenwickTree(int n) {
    
    
        tree = new int[n+1];
    }
    
    public int lowbit(int x) {
    
    
        return x & (-x);
    }
    
    public void add(int i, int val) {
    
    
        while(i < tree.length) {
    
    
            tree[i] += val;
            i += lowbit(i);
        }
    }
    
    public int query(int i) {
    
    
        int res = 0;
        while(i > 0) {
    
    
            res += tree[i];
            i -= lowbit(i);
        }
    }
}

Guess you like

Origin blog.csdn.net/zzy_NIC/article/details/130616434