Look at the following question (dynamic continuous and query):
There is an array a (length n), which requires two operations: Add (I,X): Let AIincrease x;query (A, B): Ask aa+aa+1+...+abthe and;For simulation, the worst time complexity for each query operation is O (n), which is slower when n is larger. With the prefix and also does not improve efficiency (each time the add operation is the worst O (n))。 There is a data structure that can be initialized in O (n) time, execute an Add operation or query prefix with the speed of O (Logn), and thus perform a query operation. First, let's introduce "lowbit". For a number x,lowbit (x) is the number represented by the rightmost 1 in the binary of X, for example lowbit (20) = 4, because 20 of the binary is 10100, the rightmost 1 represents 4. How to calculate lowbit? Very simple, lowbit (x) =x&-x. This is because negative numbers are kept in complement, and-X is equivalent to (~x) +1. Example (with 8-bit calculation): 20 = (00010 -) -20= (11101 -Now let's introduce the binary index tree. Binary index trees are also stored in the program using arrays. (Please forgive me). In the figure, the dark gray squares represent the nodes in the tree (node 0 is the virtual node), and the gray segments represent the edges in the tree. These edges do not need to be explicitly saved; For a node x, if it is the left dial hand node of the parent node, the parent node is numbered x-lowbit (x), otherwise x+lowbit (x). There is a white strip (including itself) on the left side of each node in the figure, such as the strip of Node 4 is 1~4, and the bar of 3 is 3~3. It is not difficult to find that the strip of Node X is (X-lowbit (x) +1) ~x. We then use an array of S to store all the numbers within each node of the white strip. For example, S4=a1+a2+a3+a4. This allows you to initialize the S array from left to right in an O (n) time using an auxiliary prefix and arrays. The code is as follows:
1 intN;2 intS[MAXN],A[MXAN],S1[MAXN];3 intbegin ()4 {5memset (S1,0,sizeof(S1));6 for(intI=1; i<=n;i++)7 {8s1[i]=s1[i-1]+A[i];9s[i]=s1[i]-s1[i-lowbit (i)];Ten } One}View Code
Finally, let's implement the add operation and the query operation. For the node I of an add operation, does its modification affect those nodes? Obviously, the node below it (Lowbit is smaller) will not be affected, and the node on its left side will not be affected, so just consider the first node on its right and lowbit larger than it, and the white bar of this node must cover X. Obviously, this node is numbered I+lowbit (i). Next, the X-nodes don't need to be considered, so let's consider the I+lowbit (i) node. As with the above, just consider the first node on its right and lowbit larger than it, so you just need to let i+=lowbit (i). The code is as follows:
1 void Add ( int i,int X) 2 3 // 4 // A[I]+=X; 5 while (I<=n) 6 { 7 s[i]+=x;i+=lowbit (i); 8 9 }
View Code
The query prefix and the method are similar, just i+=lowbit (i), changed to I-=lowbit (i); the proof method is no longer described here, similar to the above. The code is as follows:
1 intQuery2 (inti)2 {3 intsum=0;4 while(i!=0)5 {6sum+=s[i];i-=lowbit (i);7 }8 returnsum;9 }Ten intQueryintLintR) One { A returnQuery2 (R)-query2 (l1); -}View Code
Finally, if you have any suggestions, please ask.
C + + Utility data structure: Two-fork Index tree