The original: A daily walkthrough of the classic Algorithm--a tree array of question tenth
There is a kind of data structure is magical, mysterious, it shows the bit operation and array combination of magic charm, too good, it is a tree-like array, this data structure is not a god-man can not be found.
One: the approximate order
If I have a need now, that is, to frequently ask for the first n of the array, and there are some numbers in the group of frequent changes, then how can we achieve such a demand? Of course, we can go
Rely on a real project.
① Traditional method: Modify the Index to O (1), but the first n and O (n).
② Space Change Time method: I open an array sum[],sum[i]=a[1]+....+a[i], then a bit of meaning, the N and O (1), but the modification is O (N), this is because my sum[i]
There's too much data involved, so the question is, can I just save some a[i in the corresponding sum[i]? OK, let's take a look at the picture below.
We can see that the distribution of s[] becomes a tree, interesting, let's look at the value of what A[i] is stored in s[i].
S[1]=A[1];
S[2]=A[1]+A[2];
S[3]=A[3];
S[4]=A[1]+A[2]+A[3]+A[4];
S[5]=A[5];
S[6]=A[5]+A[6];
S[7]=A[7];
S[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
The reason for this distribution is that we are using a formula like this: S[i]=a[i-2k+1]+....+a[i].
Where: K in 2k represents the number of layers in the tree currently s[i], its value is the number of consecutive 0 in the binary of I, 2k that is to say S[i] contains which a[],
For example: i=610=01102; one can be found at the end of a continuous 0, that is, k=1, then S[6] is the second layer in the tree, and there are 21 items in s[6], then we find the starting item:
A[6-21+1]=A[5], but the value of k in coding is still a bit cumbersome, so we use more dexterous lowbit technology, namely: 2k=i&-i.
Then: s[6]=a[6-21+1]=a[6-(6&-6) +1]=a[5]+a[6].
Two: Code
1: The Magical lowbit function
1 #region The starting subscript for the current sum sequence 2//<summary> 3//The starting subscript for the current sum sequence 4// </summary> 5// <param Name= "I" ></param> 6 //<returns></returns> 7 public static int lowbit (int i) 8 {9 return I &-i;10 } #endregion
2: Find the top N and
For example, how to find sum (6), it is obvious sum (6) =S4+S6, then how to look for S4? That is to find all of the largest subtrees before 6, it is clear that the sum of the complexity is LOGN.
1 #region First N and 2// <summary> 3//For top N and 4// </summary> 5// <param name= "x" ></param> 6 //<returns></returns> 7 public static int Sum (int x) 8 {9 int ans = 0; 0 var i = x;12 (i >) + ( + ans + = sumarray[i-1];16) //maximum subtree of the current item i-= L Owbit (i); }20 return ans;22 }23 #endregion
3: Modify
If I modify the value of a[5], then the interval value of s[5],s[6],s[8] containing a[5] needs to be modified synchronously, and we can see that as long as we go back to the root along s[5],
It also has a time complexity of LOGN.
1 public static void Modify (int x, int newvalue) 2 {3 //Take out the value of the original array 4 var oldValue = arr[x]; 5 6 for (int i = x; i < arr.) Length; i + = Lowbit (i + 1)) 7 {8 //Subtract old value, change a new value 9 sumarray[i] = sumarray[i]-oldValue + newvalue;10 }11 }
The last total code:
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Diagnostics; 6 using System.Threading; 7 using System.IO; 8 9 Namespace ConsoleApplication2 {One public class program, {int[] Sumarray = new Int[8 ]; [int[] arr = new Int[8]; All public static void Main () () (); Console.WriteLine ("A value for array: { 0} ", String. Join (",", arr)); Console.WriteLine ("s array value: {0}", String. Join (",", Sumarray)); Console.WriteLine (The value of "modified A[1] is 3"); Modify (1, 3); Console.WriteLine ("Value of array A: {0}", String. Join (",", arr)); Console.WriteLine ("s array value: {0}", String. Join (",", Sumarray)); Console.read (); #region Initialize two arrays//<summary> 35//Initialize two arrays///</summ ary> Notoginseng public static void inIt () max (int i = 1; I <= 8; i++) {arr[i-1] = i; 42 4 3//Set in fact coordinates: I=1 begins with the int start = (I-lowbit (i)); var sum = 0; (Start < i) Arr[start {+ + + + +]; 51 52 start++; SUMARRAY[I-1] = sum; (+}) 61 Modify (int x, int newvalue) #endregion, public static void {62//Take out the value of the original array var oldValue = arr[x]; arr[x] = newvalue; 66 67 for (int i = x; i < arr. Length; i + = Lowbit (i + 1)) 68 {69//minus old value, for a new value of sumarray[i] = sumarray[i]-oldval UE + newvalue; The first n and the <summary> 76//For the first N and 77 </summary>//<param name= "x" ></param>//<returns></returns> P ublic static int Sum (int x) Bayi {0 = + + +/-n = var i = x; whil E (i > 0) (sumarray[i-1): 89 90//maximum subtree of the current item 91 I-= lowbit (i); 94 return ans; 98 #region The beginning subscript of the current sum sequence, or//<summary>100//Current S Start Subscript 101//</summary>102//<param name= "I" ></param>103//<RETURNS&G for UM series t;</returns>104 public static int lowbit (int i) 106 return I &-i;107}1 #endregion109}110}
A daily walkthrough of the classic Algorithm--tree-like array of the tenth question