The function of a tree array is to find intervals and to do some updates.
The time complexity of the segment tree and the tree array is Nlogn compared to the segment tree, but in space utilization, we know that the segment tree is close to two forks and the space required is 4 times times n, but our tree array has the same space as N and has obvious advantages in code.
Here we look at two pictures:
The tree-like array is the c[], which represents the following numbers.
Here we can see that all the odd positions will represent itself, such as 1,3,5,7 ... They only contain their own
All multiples of 2 will contain a number in front of it, such as 2,4,6,8 ... In addition to themselves, it also contains the first number of the and.
All multiples of 4 will contain the previous two numbers, such as 4,8 ... Not only contains itself and it precedes a number, but also contains the and of the first two numbers.
All multiples of 8 will contain the previous 4 numbers such as 8 ...
......
All the numbers that can be divisible by 2^n represent the number of 2^n from before that point.
By the above rule, if we ask for 1~n's and, we just need to split it into a binary number combination.
For example, the sum of 1~45, is equal to C32+C40+C44+C45, here because C32 represents 1~32 and (can be divisible by 32), C40 represents 33 to 40 and (can be divisible by 8), C44 represents 41 to 44 and (can be divisible by 4), C45 represents 45 to 45 of the sum.
So we can use the tree-like array to achieve time is NLOGN, space is n efficiency.
So how do we make it work? If we're looking for 1~n's and.
First we have to build this tree array.
We still step from left to right.
If n=8, our 8 numbers are 1 8 7 6 5 2 4 3
We add the first point, c1=1, then the reverse push, C2 will contain C1 values, so C2=C2+C1,C4 will contain C2 values, so c4=c4+c2, the same c8=c8+c4. So the first time we built the tree was this.
The second time we add 2, then obviously the 2,4,8 point will be updated.
The third time we join point 3, only 3,4,8 will be updated.
Four times we add 4, only 4 and 8 to update.
Similarly, add 5 update 5,6,8, add 6 update 6, 8, add 7 update 7, 8, add 8 update 8.
Manual simulation We will, how to implement it in code, perhaps you have a lot of ideas, but may not be as simple as the following:
int lowbit(int x){ return x&(-x);}void modify(int x,int n,int val){ for(int i=x;i<=n;i=i+lowbit(i)) { c[i]=c[i]+val; }}
The second function everyone should be able to understand, separated by the corresponding location plus the value of that point, but this is how to calculate the distance between the position, the logical operators may be very unfamiliar, here is an example:
We all know that the binary of 5 is 0000 0101, then-5 of the binary is 1111 1011, (binary number is negative is first bitwise negation, and then the last one + 1), now 5& (-5) binary is 0000 0001, because the & operator only 1&1= 1, all other cases are 0.
Here you can find that all the odd binary end is 1, we no matter the front, after the last position is 0, plus 1 is the end of 1, the other bit and the original opposite, only the end and the original is 1, so the result is 1. That is, we update the odd points and then update the location of the point +1.
If our value is a multiple of 2 (not including 2^2,2^3, etc.), then the end is 10, the same way regardless of the front, take the inverse 01, add 1 to 10, the front and the original number is the opposite, the end two is the same, so the result is 2, that is, we have a multiple of 2 to continue to update the point of two Like 2 jumps to 4, 6 jumps to 8.
Similarly, for a multiple of 4, the end is 100, the inverse +1 is still 100, the result is 4, so the position of 4 to be updated to jump to 8. 12 of the position to jump to 16.
Similarly, for multiples of 2^n, the end is 1000 ... (n 0), take anti +1 is itself, the result is 2^n, so the point to jump to that point +2^n point.
Until the next point to update is not in the interval.
This completes the creation of the tree array.
For the query, we can do according to the reverse thinking of the achievements, we can take the above 45 example into the following code manual simulation, obtained is 1 to X and.
int getsum(int x){ intsum=0; for(int i=x;i>=1;i=i-lowbit(i)) { sum=sum+c[i]; } returnsum;}
Finally we ask for the interval X-y and the time, only need to use 1~y and minus 1~ (x-1) of the and on the line.
Here is a test code for you to read carefully.
#include <iostream>#include "stdio.h"Const intN = the;intC[n];using namespace STD;intLowbit (intx) {returnx& (-X);}voidModifyintXintNintVal) { for(intI=x;i<=n;i=i+lowbit (i)) {c[i]=c[i]+val; }}intGetsum (intx) {intsum=0; for(inti=x;i>=1; I=i-lowbit (i)) {sum=sum+c[i]; }returnsum;}intMain () {printf("Please enter 10 number \ n"); for(intI=1; i<=Ten; i++) {intTscanf("%d", &t); Modify (I,Ten, t); }printf("The values for the tree array are: \ n"); for(intI=1; i<=Ten; i++) {printf("%d", C[i]); }printf("\ n from 1 to I and the difference is \ n"); for(intI=1; i<=Ten; i++) {printf("%d", Getsum (i)); }}
The results of the simulation run are as follows:
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Data structure tree-like array