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.