Last Updated: 5 Apr, 2021

RangeModule

Hard
Asked in company
Apple

Problem statement

A range module is a module that tracks the range of numbers. You have to design and implement the following interface.

addRange(left, right). This will add the half-open interval [left, right), tracking every real number in that interval. Now, adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval that are not already tracked.

queryRange(left, right) . This will return true when every real number in the interval [left, right) is currently being tracked.

removeRange(left, right), this will stop tracking every real number currently being tracked in the interval [left, right).

Note

A half open interval [left, right) denotes all real number left <= x < right.

You will be given Q queries where

1 -> addRange(left, right)
2 -> queryRange(left, right)
3 -> removeRange(left,right)

Your task is to find the answers to the above Q queries.

Example

1 10 20
3 14 16
2 10 14
2 13 15
2 16 17

Here the outputs will be -1, -1, true, false, true as - 
In the first query range [10,20), it is being tracked. After that, in second query range [14,16) is removed. So the range being tracked becomes [10,14) U [16,20).

In the third query, we are checking if [10,14) range is being tracked so we will return true. 

In the fourth query, we are checking if [13,15) is being tracked so will return false.

In the fifth query, we are checking if [16,17) is being tracked, so we will return true.
Input format
The first line of input contains an integer ‘T’ denoting the number of test cases to run. Then the test case follows.

The first line of each test case contains an integer ‘Q’ denoting the number of queries to be answered.

Then the next 'Q' lines contain three space-separated integers the first integer representing the type of query and two integers left and right.
Output Format
For each test case, for all the call of the query of type:-
1- add the half-open interval [left, right). We print -1 whenever this operation is called.
2- return true or false
3- remove the half-open interval [left,right). We print -1 whenever this operation is called.
Note:
You don’t need to print anything or take input. This already has been taken care of. Just implement the function.
Constraints
1 <= T <= 10
0 < left < right < 10^9 in all calls to addRange, queryRange, removeRange.
The total number of calls to 1st query in a single test case is at most 1000.
The total number of calls to  2nd query in a single test case is at most 5000.
The total number of calls to  3rd query in a single test case is at most 1000.

Time limit - 1sec

Approaches

01 Approach

Approach:

 

Use a map to save the disjoint intervals. For example, M['LEFT'] = 'RIGHT' means there is an interval ['LEFT', 'RIGHT'). 

 

Algorithm:

    Define one map ‘M’

  1. For query type 1, we have to implement an addRange function.
    1. Define a function addRange(), this will take ‘'LEFT'’, 'RIGHT',
    2. removeRange('LEFT', 'RIGHT')
    3. M['LEFT'] := 'RIGHT'
    4. ‘i’t := location where 'LEFT' is present in m
    5. if ‘it’ is not equal to first element of ‘M’ and second value of of previous of it is same as 'LEFT', then −
      1. (decrease it by 1)
      2. second of ‘it’ := 'RIGHT'
      3. delete 'LEFT' from ‘M’
    6. if ‘it’ is not equal to previous of last element of ‘M’ and first of next of it is same as 'RIGHT', then −
      1. second of ‘it’ := second of next(‘it’)
      2. delete next(‘it’) from ‘M’
  2. For query type 2 , we have to implement a function to check if the range [l, r) is being tracked.
    1. Define a function queryRange(), this will take 'LEFT', 'RIGHT',
    2. ‘it’ := location of a subpart of ‘M’ all smaller value than 'LEFT'
    3. if ‘M’ is empty or it is same as first element of ‘M’, then −
      1. return false
    4. (decrease it by 1)
    5. return true when second of ‘it’ >= 'RIGHT'
  3. For query type 3, we have to implement a function to remove range [l,r)
    1. f ‘M’ is empty, then −
      1. return
    2. ‘it’ := location of a subpart of ‘M’ all upper value than 'LEFT'
    3. if it is not equal to first element of ‘M’, then −
      1. (decrease it by 1)
    4. Define an array ‘V’
    5. while (it is not equal to last element of ‘M’ and first of ‘it’ < 'RIGHT'), do −
      1. if first of ‘it’ < 'LEFT' and second of ‘it’ > 'LEFT', then −
        1. 'TEMP' := second of ‘it’
        2. second of it := 'LEFT'
        3. if 'TEMP' > 'RIGHT', then: m['RIGHT'] := 'TEMP'
      2. otherwise when first of it >= 'LEFT', then −
        1. Insert first of it at the end of ‘V’
        2. if second of ‘it’ > 'RIGHT', then −
          1. M['RIGHT'] := second of it
      3. (increase it by 1)
    6. for initialize ‘i’ := 0, when ‘i’ < size of ‘V’, update (increase ‘i’ by 1), do −
      1. delete V[i] from ‘M’