Fenwick tree Introduction

Fenwick tree can solve any kind of problem:

Here the subject to expand by a simple introduction, a first input of an array of length n, then we have the following two operations:

  1. Enter a prefix number m, the output array subscript 1 ~ m and
  2. Modify the value of a specified number of subscripts

Repeatedly performing the above two operations


Method unusual
for an array, the prefix request if 1 ~ m and we can begin to be summed from the number of the subscript m 1, n for the operations, the time complexity is O (n ^ 2), for modified value, we can find the index number directly to modify, n times the operating time complexity of O (n), n in the array larger than the opening in the time of the prefix and efficiency appears low

  • So it was suggested that an optimized way:
    initial save us with an array of initial values for each position A, and then use an auxiliary array B is stored in the front of the i-th subscript i when A and array (prefix and), then we need, when m number of prefixes and used directly as long as the index of the array B can query, n-queries, time complexity is O (n), but this time, for a single point updating maintenance consumption value, the original O (n) becomes O (n ^ 2), because each time the updated values will affect a single point on the array have been computed B value prefix and the back, the need to constantly update the value of the array B, n is a natural maintenance update consumption becomes O (n ^ 2), the efficiency becomes low update

Fenwick tree
so if there is a way to make queries and updates are small time complexity of some of it, or at least acceptable, Fenwick tree here will introduce how to deal with the prefix and the query and update a single point, for the n-th operation , are time complexity O (nlogn)

  • Borrowing pictures on Wikipedia Baidu
    图 1.jpg
    图 2.jpg

As shown, for an array of length n, A is the initial value stored in the array of the array, the introduction of an auxiliary array C (we established a tree array by array C)

The C1 = the A1 the
C2 = the C1 + the A2 = the A1 + the A2 the
C3 = the A3 the
C4 = the C2 + the C3 + the A4 = the A1 + the A2 + the A3 + the A4
C5 is = the A5 the
C6 = C5 is + the A6 = the A5 + the A6 the
C7 = the A7 of
C8 = the C4 + the C6 + C7 + A8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

We call C [i] value of the subscript i is the number of the jurisdiction of the numbers and, C [8] is to be stored under the jurisdiction of those numbers 8 and number (there are eight), and subscript i governed by the number of number of elements compared to two 2 ^ k (k is the number of i is 0 at the end of the binary) two examples queries and m5 and m8 lower subscript number jurisdiction

  • 8 = 1000, the end of the 3 0, so k == 3, is governed by the number 2 ^ 3 == 8, C8 is 8 and the number of
  • 5 = 0101, 0 is not the end, it is k == 0, is governed by the number 2 ^ 0 == 1, C5 and is a number (which itself A5)

As for the number m of input, we ask for the number m of the number of prefixes and A1 ~ Am ( This assumes Fenwick tree has been established that the value of C1 ~ C8 has been determined, do not worry, it will make at the bottom of this article the process of establishing Fenwick tree to explain, because it is in demand and the prefix, it is assumed that C arrays already available, right ) are two examples m7 and m6 (sum (i) indicates finding the number of prefixes and i)

  • m == 7 sum (7) = C7 + C6 + C4
    So how do we get number 7 which is composed of several C [i] obtained by summing it (C4, C6, C7 how obtained), here introduces a ingenious way:
    after a query for m, converts it into a binary, the position of the end of the continuous operation 1 -1, 0 is stopped until all
    binary 0111 to 7 (obtained C7), the first end 0111 of the position -11 to give 0110 == 6 (C6 obtained), then position -1 to 1 at the end of 0110, to give 0100 == 4 (C4 obtained), to give the final -10,100 end position (end signal) 0000 , calculation is stopped, thus C7, C6, C4 all been, after the summation is its prefix and m == 7
  • SUM == 6 m (6) C4 = C6 +
    m == 6 is the same, the first switch equal to a binary 0110. After two converted 0100 (C4) and 0000 (end signal), then the sum the same has also been projected results

Here to introduce an efficient method, lowbit (int m), which it is a function, its role is to determine the position of the end of the binary representation of m is 1, to query for the prefix and m, m = m - lowbit (m ) on behalf of the end of the continuous binary 1 1 operation, continued to perform until the end of m == 0, you can get a prefix and which consists of several Cm, very clever, lowbit is the core of Fenwick tree

int lowbit(int m){ return m&(-m); } 

About m & (- m) a lot of children's shoes may be confused, then you have to mention what negative numbers stored in the form of computer memory, is the complement of a negative number is stored in the computer, such as the binary representation of 13 is 1101, then -13 and the binary bitwise binary 13, and the end of +1, i.e., 0010 + 0001 = 0011, 1101 & 0011 == 0001 then, it is clear that to obtain a binary position 13 m == 1 is the end of 2. 0 orientation, the 13--0001 == 12, 12 again performs operation lowbit, 1100 & 0100 == 0100, is also very easy to obtain the location of the end of a 12 m == 2 is a binary orientation 2 will 12--0100 == 8, 8 and then the operation performed lowbit, 0100 & 1100 0100 == give == 8 m 2 binary bits are in position 2, 8--0100 == 0 (end operation), obtained through 13 cycles, 12,8, then the sum (13) == C13 + C12 + C8

Seeking a prefix code and

int ans = 0;
int getSum(int m){ while(m > 0){ ans += C[m]; m -= lowbit(m); } } 

For n times and prefix query time complexity of O (nlogn)
next to explain a single point of update value
for x number of input values, a value requires the additional value to its value, we have to win again to FIG.
图 3.jpg

Suppose x2, value5, we first find the A [2] position, we observe that, if a modified A [2] value, then the jurisdiction A [2] is C [2], C [4 ], C [8] prefix and should add value (all ancestor nodes), and then the query is similar to how we get it all ancestor nodes C2 (C2 because the same indices and A2 so that queries from C [x] updating start), is still a clever method described above, but we turn it upside down
to the position you want to update the value of x, we put x into a binary, continuous position +1 to last a binary 1, until it reaches the maximum array subscript n end

  • For the example given x2, under the assumption that the upper limit standard array n8, x is equal to binary 0010 (C2), the position of the end of the 1 +1, to obtain 0100 (C4), the position of the end of the 1 +1, to give 1000 (C8), the end of the cycle, for C2, C4, C8 and prefix value should be added, of course, can not forget the end value of a [2] a + value, the value of a single point updating process

Given the code

void update(int x, int value){ A[x] += value; //不能忘了对A数组进行维护,尽善尽美嘛 while(x <= n){ C[x] += value; x += lowbit(x); } } 

For the n-th refresh operation, as the same time complexity O (nlogn)

There is a precautions, we seek to update prefix and with a single point, Fenwick tree C is used to direct use, then the question is, when will establish good tree, I do not know how? ?

In fact, for an input array A, the process of our once read, can be thought of as a process of continuously updated values ​​(A1 ~ An update from the 0 to the A input of our [I]), while it reads a [i], while the C [i] related to the ancestor node values ​​updated after the completion of input Fenwick tree C also established successful

Guess you like

Origin www.cnblogs.com/elvisHuster/p/12593657.html