Segment tree (B): interval modification

    On one point describes the tree line and modify the query interval, in fact, tree line also can do more. This section discusses the question of amending section.

    Given a $ n $-element array $ A_1, A_2, ..., A_n $, your task is to design a data structure that supports the following two operations:

  • $ Add (L, R, v) $: the $ A_L, A_ {L + 1}, ..., full incremental value A_R $ $ $ V
  • $ Query (L, R) $: calculated subsequence $ A_L, A_ {L + 1}, ..., A_R $ elements and maximum and minimum values

    Point modify only affect $ logn $ nodes, but in the worst case interval modification will affect all nodes in the tree, for example, if the operation of the entire range execute $ add $, all nodes $ sum $ It will change. How to do it?

    Recall a conclusion when previous range query: Any interval can be broken down into no more than $ 2h $ disjoint intervals. With this conclusion, we can "split up", put a $ add $ decompose into operation no more than $ 2h $ operations, the segment recorded node tree.

    Maintenance information also needs change, if still represented by $ $ sum [o] "$ O $ node corresponding to the interval and the number of all", then the Add $ $ $ operations modify all in the worst case $ SUM ($ add $ Whether there is no decomposition). The solution is to $ sum [o] $ definition to "execute only if the Add $ $ $ O $ operation node and the descendant node, the node $ O $ interval corresponding to the sum of all numbers." Such additional information can still be easily maintained, and the original number of nodes per the Add $ $ affected to become $ O (h) $.

    Maintenance code is as follows:

. 1  void Maintain ( int O, int L, int R & lt)
 2  {
 . 3      IF (R & lt == L) MINV [O] = A [L]; // If the node is a leaf 
. 4      the else   MINV [O] = min (MINV [ 2 * O], MINV [ 2 * + O . 1 ]);     // if the non-leaf node 
. 5      MINV [O] + = ADDV [O];      // consider the add operation 
. 6  }
 . 7  
. 8  int Cl, Cr, V;   // interval modification, [Cl, Cr] + = V; 
. 9  void Update ( int O, int L,int R)  //
10 {
11     int M = L + (R-L) /2;
12     if(cl <= L && R <= cr)  addv[o] += v;
13     else
14     {
15         if(cl <= M)  update(2*o, L, M);
16         if(cr > M)  update(2*o+1, M+1, R);
17     }
18     maintain(o, L, R);
19 }

    Note that, at this time MINV recursive boundary nodes is the add operation, MINV its child nodes (i.e., sub-section) is not accurate, because the add operation does not consider the influence.

    Overall before with the same query, but have to consider the impact of its ancestor node. Therefore, we add a parameter $ add $ recursive queries, indicating the current range of desired ancestor node $ add $ value and (not including itself, because the add mark itself has been considered in maintain), as follows:

 1 int ql, qr;     //区间查询,min{ql,qr}
 2 int query(int o, int L,int R, int add)
 3 {
 4     int M = L + (R - L) / 2;
 5     if(ql <= L && R <= qr)  return minv[o] + add;
 6     else
 7     {
 8         int ans = INF;
 9         add += addv[o];
10         if(ql <= M)  ans = min(ans, query(2*o, L, M, add));
11         if(qr > M)  ans = min(ans, query(2*o+1, M+1, R, add));
12         return ans;
13     }
14 }

    Achievements of the operation point to modify the same, it is omitted.

 

Guess you like

Origin www.cnblogs.com/lfri/p/11105222.html