range queries
play

Range Queries Part 2: Segment Trees and Lazy Propagation Lucca - PowerPoint PPT Presentation

Range Queries Part 2: Segment Trees and Lazy Propagation Lucca Siaudzionis and Jack Spalding-Jamieson 2020/02/06 University of British Columbia Announcements A2 is due Sunday!!! Jack will be hosting additional office hours from


  1. Range Queries Part 2: Segment Trees and Lazy Propagation Lucca Siaudzionis and Jack Spalding-Jamieson 2020/02/06 University of British Columbia

  2. Announcements • A2 is due Sunday!!! • Jack will be hosting additional office hours from 3:30-4:30 on Friday in X237. • Written Report requirements and rubric will be posted soon. 1

  3. Survey Talk • Details about the written report? • Slides logistics. • Assignment is too long. • Assignment is too hard. • Judge’s feedback is nearly useless. • Lecture speed. 2

  4. Remember this Problem? Given an array A of N ≤ 10 6 numbers, answer Q ≤ 10 6 queries of the form “What is the minimum number in the subarray A [ l .. r ]?” This is called Range Minimum Query (RMQ). 3

  5. Range Minimum Query Recall that we solved this using binary jumping: f ( i , p ) = the minimum number in A [ i .. i + 2 p − 1]. f ( i , 0) = . . . , f ( i , p ) = . . . min A [ l .. r ] = min { f ( l , q ) , f ( r − 2 q + 1 , q ) } . 4

  6. Range Minimum Query, Point Updates Given an array A of N ≤ 10 6 numbers, answer Q ≤ 10 6 queries and updates of the following type: 1. Output the minimum number in the subarray A [ l .. r ]. 2. Update A [ i ] to k . Naive solution: O (1) per update, O ( N ) per query. Binary jumping doesn’t work! It’s very slow to update instead. Let’s try a different way of splitting our array into chunks... 5

  7. Segment Tree Design Let’s assume that N is a power of two (if not, pad the array until it is). We’ll make a perfect binary tree where each node represents a segment of the array. • The leaves represent segments with one element. • The root represents the whole array. • Each non-leaf represents the union of the segments of its two children. • Perfect binary tree with lg N layers, so 1 + 2 + 4 + · · · + N = 2 N − 1 nodes in total. Each node in the tree will store the answer for that segment (in our range-minimum query problem, the minimum for that segment). 6

  8. Segment Tree Design How do we efficiently compute the answer for a segment? If we’re at a node representing the segment [ l , r ], then our left child has the minimum of the segment [ l , m ] and our right child has the minimum of the segment [ m + 1 , r ] (where m = ( l + r ) / 2). The minimum of our segment is the minimum of the values at our two children! 7

  9. Segment Tree Design How do we perform updates (what do we need to change when we update A [ i ] to k )? Obviously we need to update the leaf node for the i th element. The parent of this node depends on this, so we’ll need to update it as well, then update its parent, and so on until we reach the root. O (log N ) to update, since we only update on the path from leaf to root in a tree with depth lg N . 8

  10. Point Update, Visualized (Sum Segment Tree) 9

  11. Point Update, Visualized (Sum Segment Tree) 10

  12. Point Update, Visualized (Sum Segment Tree) 11

  13. Point Update, Visualized (Sum Segment Tree) 12

  14. Point Update, Visualized (Sum Segment Tree) 13

  15. Segment Tree Design What about querying for the minimum element in the range [ x , y ]? We can decompose this range into subranges in the segment tree. We’ll find the subranges recursively: • Start at the root and recurse downards. • Suppose the node we’re at represents the segment [ l , r ]. There are 2 cases: • If [ l , r ] ⊂ [ x , y ] then return the value of the node. • Otherwise, recurse on the children that aren’t disjoint from [ x , y ] and combine the answer (in this case, take the min). We can prove that at each level, we’ll consider at most 4 nodes ⇒ O (log n ) per query. 14

  16. Range Query, Visualized We want to compute the sum of all the values in the highlighted interval. 15

  17. Range Query, Visualized 16

  18. Range Query, Visualized 17

  19. Range Query, Visualized 18

  20. Range Query, Visualized 19

  21. Range Query, Visualized 20

  22. Range Query, Visualized 21

  23. Range Query, Visualized 22

  24. Segment Tree Initialization • Naive way: call update for each element ( O ( N log N )) • Faster way: fill from the leaves upwards, layer by layer ( O ( N )) Overall, our RMQ problem runs in O ( N + Q log N ). 23

  25. Segment Tree Implementation How do we implement these operations? First, to store the tree: • Store the tree nodes in an array T of length 2 N . • The root is T [1]. � i � • For a node i , its children are 2 i and 2 i + 1, and its parent is . 2 • This is just like binary heaps! • The leaf nodes are T [ N .. (2 N − 1)]. • The intermediate nodes are T [1 .. ( N − 1)]. 24

  26. Segment Tree Implementation T = array of length 2*N # N is a power of two 1 2 def pull(i): # update node i with its children's values 3 T[i] = min(T[2*i], T[2*i+1]) 4 5 def init(A): # initialize the segment tree with array A 6 # fill leaves 7 for i = 0 .. N-1: 8 T[N+i] = A[i] 9 # fill rest of tree 10 for i = N-1 .. 1: 11 pull(i) 12 const int MAXN = 100000; 1 int bit[MAXN+1]; 2 25

  27. Segment Tree Implementation def update(i, k): # change the ith element to k 1 # update the leaf 2 v = N+i 3 T[v] = k 4 # propagate changes up to the root 5 v = v / 2 6 while v > 0: 7 pull(v) 8 v = v / 2 # v = parent(v) 9 26

  28. Segment Tree Implementation def query(x, y): # query for the min value in [x, y] 1 return query(x, y, 1, 0, N-1) 2 3 def query(x, y, i, l, r): # i is the node index, and its segment is [l, r] 4 if r < x or y < l: # [l, r] completely outside [x, y] (irrelevant) 5 return infinity # the identity element for min 6 if x <= l and r <= y: # [l, r] contained in [x, y] 7 return T[i] # (don't need to recurse) 8 # recurse on children 9 m = (l + r) / 2 10 return min(query(x, y, 2*i, l, m), query(x, y, 2*i+1, m+1, r)) 11 27

  29. Segment Tree Segment trees are very flexible! We can store any kind of data in our nodes, and combine them in (almost) any way (e.g. gcd, sets and set union, polynomials and addition). 28

  30. Discussion Problem 1 Answer Q queries on an array A of the following types: 1. Update A [ i ] to k . 2. Query for the maximum-sum subarray in A [ l .. r ]. 29

  31. Discussion Problem 1 – Insight In a node, store four values: • The sum of all the elements in the segment. • The maximum sum of a subarray which starts at the left endpoint. • The maximum sum of a subarray which ends at the right endpoint. • The maximum sum of any subarray. At a node, its best subarray could lie entirely in the left child, entirely in the right child, or it could go across. Use the statistics we store for our children to compute our own! 30

  32. Range Updates, Range Queries Given an array A , answer many queries of the following types: 1. Output � A [ l .. r ]. 2. Add x to all the elements in the range A [ l .. r ]. How can we handle both at once? 31

  33. Range Updates, Range Queries Idea is similar to range updates, point queries, but now we need to be careful about managing the added values in segments. Let’s be lazy! 32

  34. Lazy Propagation • To add x to everything in [ l , r ], we’ll update the same O (log n ) segments that we look at in a query. • We’ll also update a lazy value for these segments: lazy ( i ) = the amount that was added to this segment that we need to update our children with. • When we need to visit children of this node later, we’ll “push” the lazy update down to its children. 33

  35. Lazy Propagation, Visualized 34

  36. Lazy Propagation, Visualized 35

  37. Lazy Propagation, Visualized 36

  38. Lazy Propagation, Visualized 37

  39. Lazy Propagation, Visualized 38

  40. Lazy Propagation, Visualized 39

  41. Lazy Propagation, Visualized 40

  42. Lazy Propagation, Visualized 41

  43. Lazy Propagation, Visualized 42

  44. Lazy Propagation, Visualized 43

  45. Lazy Propagation, Visualized 44

  46. Lazy Propagation, Visualized 45

  47. Lazy Propagation, Visualized 46

  48. Lazy Propagation, Visualized 47

  49. Lazy Propagation, Visualized 48

  50. Lazy Propagation, Visualized 49

  51. Lazy Propagation, Visualized 50

  52. Lazy Propagation, Visualized 51

  53. Lazy Propagation, Visualized 52

  54. Lazy Propagation, Visualized 53

  55. Lazy Propagation, Visualized 54

  56. Lazy Propagation – Implementation T = array of 2*N elements 1 lazy = array of 2*N elements, initialized to null 2 3 def pull(i): 4 T[i] = T[2*i] + T[2*i+1] 5 6 def push(i): # update node i's children with the lazy value 7 if lazy[i] is not null: 8 T[2*i] += lazy[i] * length(2*i) 9 T[2*i+1] += lazy[i] * length(2*i+1) 10 lazy[2*i] += lazy[i] 11 lazy[2*i+1] += lazy[i] 12 lazy[i] = null 13 55

  57. Lazy propagation – implementation def update(x, y, k): # add k to A[x..y] 1 return update(x, y, k, 1, 0, N-1) 2 3 def update(x, y, k, i, l, r): 4 if r < x or y < l: return # this range is irrelevant 5 if x <= l and r <= y: # range is contained: update the lazy tag 6 T[i] += k * length(i) 7 lazy[i] += k 8 return 9 m = (l + r) / 2 10 push(i) # accessing children, so need to push! 11 update(x, y, k, 2*i, l, m) 12 update(x, y, k, 2*i+1, m+1, r) 13 pull(i) # update ourselves 14 56

Recommend


More recommend