Guest User

Untitled

a guest
Jun 19th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.16 KB | None | 0 0
  1. Wood Fenwick
  2.  
  3. Fenwick tree - a data structure, a tree on the array with the following properties:
  4.  
  5. 1) allows to calculate the value of a reversible operation of G on any interval [L; R] in time O (log N);
  6.  
  7. 2) lets you change the value of any element in O (log N);
  8.  
  9. 3) requires O (N) memory, or more precisely, exactly the same as, and an array of N elements;
  10.  
  11. 4) is easily generalized to the case of multidimensional arrays.
  12.  
  13. The most common use of wood Fenwick - to calculate the sum of the segment, ie function G (X1, ..., Xk) = X1 + ... + Xk.
  14.  
  15. Wood Fenwick was first described in the article "A new data structure for cumulative frequency tables" (Peter M. Fenwick, 1994).
  16. Description
  17.  
  18. For ease of description, we assume that the operation of G, on which we build a tree - a sum.
  19.  
  20. Suppose we are given an array A [0 .. N-1]. Fenwick tree - an array T [0 .. N-1], each element of which is stored the sum of some elements of the array A:
  21.  
  22. Ti = the sum of Aj for all F (i) <= j <= i,
  23.  
  24. where F (i) - a function which we define later.
  25.  
  26. Now we can write the pseudocode for the function computing the sum on the interval [0; R], and changes in cell function:
  27.  
  28. int sum (int r)
  29. {
  30. int result = 0;
  31. while (r> = 0) {
  32. result + = t [r];
  33. r = f (r) - 1;
  34. }
  35. return result;
  36. }
  37.  
  38. void inc (int i, int delta)
  39. {
  40. for all j, for which F (j) <= i <= j
  41. {
  42. t [j] + = delta;
  43. }
  44. }
  45.  
  46. The sum function works as follows. Instead of going through all elements of the array A, it moves over the array of T, making the "jump" across the segments where possible. First, it adds to the response value of the sum on the interval [F (R); R], then takes the sum of the interval [F (F (R) -1); F (R) -1], and so on, until it reaches zero.
  47.  
  48. The function inc is moving in the opposite direction - toward increasing index, updating the value of the sum Tj only for those positions for which this is necessary, ie for all j, for which F (j) <= i <= j.
  49.  
  50. Obviously, the choice of F will depend on the speed of both operations. Now we consider a function that would achieve logarithmic performance in both cases.
  51.  
  52. We define the value of F (X) as follows. Consider the binary representation of numbers and look at its lowest bit. If it is zero, then F (X) = X. Otherwise, the binary representation of X ends in a group of one or more units. We replace all the units from this group on the zeros, and assign that number to the value of the function F (X).
  53.  
  54. This is a rather complicated description corresponds to a very simple formula:
  55.  
  56. F (X) = X & (X +1),
  57.  
  58. where k - is the bitwise logical "AND".
  59.  
  60. It is easy to see that this formula corresponds to the verbal description of the function given above.
  61.  
  62.  
  63.  
  64. We just have to learn how to quickly find the number of such j, for which F (j) <= i <= j.
  65.  
  66. However, it is easy to verify that all such numbers j are obtained from i by successive replacements of the rightmost (least significant) zero in the binary representation. For example, for i = 10, we find that j = 11, 15, 31, 63, etc.
  67.  
  68. Ironically, such an operation (replacement of the youngest unit of zero) and corresponds to a very simple formula:
  69.  
  70. H (X) = X | (X +1),
  71.  
  72. where | - is a bitwise logical "OR".
  73. The implementation of the tree Fenwick for the sum of one-dimensional case
  74.  
  75. vector <int> t;
  76. int n;
  77.  
  78. void init (int nn)
  79. {
  80. n = nn;
  81. t.assign (n, 0);
  82. }
  83.  
  84. int sum (int r)
  85. {
  86. int result = 0;
  87. for (; r> = 0; r = (r & (r +1)) - 1)
  88. result + = t [r];
  89. return result;
  90. }
  91.  
  92. void inc (int i, int delta)
  93. {
  94. for (; i <n; i = (i | (i +1)))
  95. t [i] + = delta;
  96. }
  97.  
  98. int sum (int l, int r)
  99. {
  100. return sum (r) - sum (l-1);
  101. }
  102.  
  103. void init (vector <int> a)
  104. {
  105. init ((int) a.size ());
  106. for (unsigned i = 0; i <a.size (); i + +)
  107. inc (i, a [i]);
  108. }
  109.  
  110. The implementation of the tree Fenwick for a minimum of one-dimensional case
  111.  
  112. It should be noted immediately that, since the Fenwick tree allows you to find the value of the function in an arbitrary interval [0; R], then we will not be able to find the minimum on the interval [L; R], where L> 0. Further, the values โ€‹โ€‹of all the changes should take place only in the direction of decreasing (again, because it does not get to draw the function min). This is a significant limitation.
  113.  
  114. vector <int> t;
  115. int n;
  116.  
  117. const int INF = 1000 * 1000 * 1000;
  118.  
  119. void init (int nn)
  120. {
  121. n = nn;
  122. t.assign (n, INF);
  123. }
  124.  
  125. int getmin (int r)
  126. {
  127. int result = INF;
  128. for (; r> = 0; r = (r & (r +1)) - 1)
  129. result = min (result, t [r]);
  130. return result;
  131. }
  132.  
  133. void update (int i, int new_val)
  134. {
  135. for (; i <n; i = (i | (i +1)))
  136. t [i] = min (t [i], new_val);
  137. }
  138.  
  139. void init (vector <int> a)
  140. {
  141. init ((int) a.size ());
  142. for (unsigned i = 0; i <a.size (); i + +)
  143. update (i, a [i]);
  144. }
  145.  
  146. The implementation of the tree Fenwick for the sum of two-dimensional case
  147.  
  148. As already noted, the Fenwick tree can easily be generalized to the multidimensional case.
  149.  
  150. vector <vector <int>> t;
  151. int n, m;
  152.  
  153. int sum (int x, int y)
  154. {
  155. int result = 0;
  156. for (int i = x; i> = 0; i = (i & (i +1)) - 1)
  157. for (int j = y; j> = 0; j = (j & (j +1)) - 1)
  158. result + = t [i] [j];
  159. return result;
  160. }
  161.  
  162. void inc (int x, int y, int delta)
  163. {
  164. for (int i = x; i <n; i = (i | (i +1)))
  165. for (int j = y; j <m; j = (j | (j +1)))
  166. t [i] [j] + = delta;
  167. }
Add Comment
Please, Sign In to add comment