CPSC 490: Problem Solving in Computer Science Assignment 4 is due - - PowerPoint PPT Presentation

cpsc 490 problem solving in computer science
SMART_READER_LITE
LIVE PREVIEW

CPSC 490: Problem Solving in Computer Science Assignment 4 is due - - PowerPoint PPT Presentation

Lecture 13: Segment trees Lazy propagation, binary search Henry Xia, Brandon Zhang based on CPSC 490 slides from 2014-2018 2019-03-04 University of British Columbia CPSC 490: Problem Solving in Computer Science Assignment 4 is due


slide-1
SLIDE 1

CPSC 490: Problem Solving in Computer Science

Lecture 13: Segment trees – Lazy propagation, binary search

Henry Xia, Brandon Zhang

based on CPSC 490 slides from 2014-2018

2019-03-04

University of British Columbia

slide-2
SLIDE 2

Announcements

  • Assignment 4 is due tonight.
  • Presentation 2 topics will be posted shortly.
  • Presentation 2 dates are the last 3 classes.
  • Some kind of visual aid (e.g. slides) will be required for this set of presentations.

1

slide-3
SLIDE 3

Last time...

  • We described a segment tree, a data structure which allows us to:
  • Update a point x to a new value.
  • Aggregate the values in a range [l, r].
  • Now, let’s make it more powerful!

2

slide-4
SLIDE 4

Warmup

Given an array A, support the following two operations:

  • Change A[i] to k.
  • Query for the maximum value in [l, r], and the number of times that the maximum

element appears.

3

slide-5
SLIDE 5

Warmup – Solution

Just store the max value and the number of times for each node! (Combining nodes leħt as exercise.)

4

slide-6
SLIDE 6

Range updates, point queries

Given an array A, answer many queries of the following types:

  • 1. Output the value of A[x].
  • 2. Add x to all elements in the range A[l..r].

5

slide-7
SLIDE 7

Range updates, point queries

Let’s just try switching the code for updating and querying. The node for the segment [l, r] stores the total amount added to this segment (but not to its children’s segments). To get the value of A[x], we just add up the values of x’s ancestors (these are the segments that contain x).

6

slide-8
SLIDE 8

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?

7

slide-9
SLIDE 9

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!

8

slide-10
SLIDE 10

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.

9

slide-11
SLIDE 11

Lazy propagation, visualized

10

slide-12
SLIDE 12

Lazy propagation, visualized

10

slide-13
SLIDE 13

Lazy propagation, visualized

10

slide-14
SLIDE 14

Lazy propagation, visualized

10

slide-15
SLIDE 15

Lazy propagation, visualized

10

slide-16
SLIDE 16

Lazy propagation, visualized

10

slide-17
SLIDE 17

Lazy propagation, visualized

10

slide-18
SLIDE 18

Lazy propagation, visualized

10

slide-19
SLIDE 19

Lazy propagation, visualized

10

slide-20
SLIDE 20

Lazy propagation, visualized

10

slide-21
SLIDE 21

Lazy propagation, visualized

10

slide-22
SLIDE 22

Lazy propagation, visualized

10

slide-23
SLIDE 23

Lazy propagation, visualized

10

slide-24
SLIDE 24

Lazy propagation, visualized

10

slide-25
SLIDE 25

Lazy propagation, visualized

10

slide-26
SLIDE 26

Lazy propagation, visualized

10

slide-27
SLIDE 27

Lazy propagation, visualized

10

slide-28
SLIDE 28

Lazy propagation, visualized

10

slide-29
SLIDE 29

Lazy propagation, visualized

10

slide-30
SLIDE 30

Lazy propagation, visualized

10

slide-31
SLIDE 31

Lazy propagation – implementation

1

T = array of 2*N elements

2

lazy = array of 2*N elements, initialized to null

3 4

def pull(i):

5

T[i] = T[2*i] + T[2*i+1]

6 7

def push(i): # update node i's children with the lazy value

8

if lazy[i] is not null:

9

T[2*i] += lazy[i] * length(2*i)

10

T[2*i+1] += lazy[i] * length(2*i+1)

11

lazy[2*i] += lazy[i]

12

lazy[2*i+1] += lazy[i]

13

lazy[i] = null

11

slide-32
SLIDE 32

Lazy propagation – implementation

1

def update(x, y, k): # add k to A[x..y]

2

return update(x, y, k, 1, 0, N-1)

3 4

def update(x, y, k, i, l, r):

5

if r < x or y < l: return # this range is irrelevant

6

if x <= l and r <= y: # range is contained: update the lazy tag

7

T[i] += k * length(i)

8

lazy[i] += k

9

return

10

m = (l + r) / 2

11

push(i) # accessing children, so need to push!

12

update(x, y, k, 2*i, l, m)

13

update(x, y, k, 2*i+1, m+1, r)

14

pull(i) # update ourselves

12

slide-33
SLIDE 33

Lazy propagation – implementation

1

def query(x, y):

2

return query(x, y, 1, 0, N-1)

3 4

def query(x, y, i, l, r):

5

if r < x or y < l: # range is irrelevant

6

return 0

7

if x <= l and r <= y: # range is contained

8

return T[i]

9

m = (l + r) / 2

10

push(i) # accessing children, so need to push!

11

return query(x, y, 2*i, l, m) + query(x, y, 2*i+1, m+1, r)

13

slide-34
SLIDE 34

Problem 1 – Slightly difgerent problem

Given an array A, answer many queries of the following types:

  • 1. Output ∑ A[l..r].
  • 2. Assign the value x to all the elements in the range A[l..r].

14

slide-35
SLIDE 35

Problem 1 – Solution

Use a lazy segment tree! The lazy updates need to be handled a little difgerently:

  • Instead of summing the lazy values, we’ll assign them.
  • When pushing, instead of adding the lazy, we’ll set the tree value to the lazy (times

the length).

15

slide-36
SLIDE 36

Problem 2 – Colouring

Given an array A of k ≤ 60 distinct colours, answer many queries of the following types:

  • 1. Colour the segment [l, r] with the colour c.
  • 2. Output the number of distinct colours in the range [l, r].

16

slide-37
SLIDE 37

Problem 2 – Solution

Each segment tree node stores the set of colours that are in its segment. To get the result for a node (pull), take the set union of its two children. We can use bitmasks to store the set. Then, a set union is the bitwise OR.

  • To colour [l, r] with colour c, assign everything in the range to the set {c}.
  • To get the number of distinct colours, make a range query and output the number of

elements in the set.

17

slide-38
SLIDE 38

Problem 3 – Order-statistic set

Implement a multiset storing integers in the range [0, N]. The multiset should support the following operations:

  • add(x): add x to the multiset
  • remove(x): remove x from the multiset
  • count(l, r): output the number of elements in the multiset that are between l

and r

  • find(k): return the kth smallest element

18

slide-39
SLIDE 39

Problem 3 – Solution

We’ve seen many ways to implement this, but one way is with a segment tree! Each node will store the sum of its segment.

  • add(x): add 1 to index x
  • remove(x): subtract 1 from index x
  • count(l, r): range sum of [l, r]

What about find?

19

slide-40
SLIDE 40

Problem 3 – Solution

  • Naive solution—binary search on the answer. To check if x is the kth largest element,

check if the range sum [0, x] is larger or smaller than k.

  • O(log n) iterations of binary search, each of which performs an O(log n) query ⇒

O(log2 n) in total But, we can do better...

  • We can view the segment tree like a binary search tree.
  • Start at the root node. If the sum of our leħt child is

k, recurse on the right child, else recurse on the leħt.

20

slide-41
SLIDE 41

Problem 3 – Solution

  • Naive solution—binary search on the answer. To check if x is the kth largest element,

check if the range sum [0, x] is larger or smaller than k.

  • O(log n) iterations of binary search, each of which performs an O(log n) query ⇒

O(log2 n) in total But, we can do better...

  • We can view the segment tree like a binary search tree.
  • Start at the root node. If the sum of our leħt child is < k, recurse on the right child,

else recurse on the leħt.

20

slide-42
SLIDE 42

Problem 4 – More statistics

Implement a multiset supporting all the previous operations, as well as

  • find_next(x): return the smallest element in the set larger than x

21

slide-43
SLIDE 43

Problem 4 – Solution

We can still do this in O(log2 n) naively, but let’s try to find something faster...

  • We need to find the smallest y such that the range sum of [x + 1, y] is greater than 0.
  • We’ll “go up” then “go down” in the segment tree.
  • Start at the leaf node representing x + 1.
  • If the range sum of our segment is greater than 0, then the answer is in our segment. Go

down using the method described in the last problem.

  • Otherwise, we need to find a bigger segment to the right of us with a nonzero sum, so

we’ll “go up”.

  • If we’re a right child, go to the node to the right of our parent.
  • Otherwise, go to our parent.

We only go up and down once, and the depth of the tree is O(log n), so the runtime is O(log n). Before starting at a leaf, remember to push down!

22

slide-44
SLIDE 44

Problem 5 – Shopping

Input: a store with N items in a row, with difgerent prices pi. Q customers will enter the store. Each customer has a difgerent amount of money vi, and will walk through the store from leħt to right between items li and ri. Whenever a customer encounters an item, they will buy as many copies of it as they can afgord. Output: for each customer, the amount of money they’ll have leħt aħter exiting.

Source: ACM-ICPC Pacific Northwest Regional 2016

23

slide-45
SLIDE 45

Problem 5 – Solution

Observation 1: the answer for the ith customer is (((vi mod pli) mod pli+1) mod . . . ) mod pri. Observation 2: if a customer can buy the ith item, aħterward they will have at most half the money they had before. This means that each customer buys O(log N) distinct items. Now, all we need to do is find these items quickly. Formally, given an index i and an amount of money v, we need to find the smallest index j such that j > i and pj ≤ v. Build a segment tree on the pi’s storing the minimum value in the range, and apply our “binary search” algorithm to find each j. Time complexity: O(N log2 N)

24