0715. Range Module

# 715. Range Module#

## 题目 #

A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the following interfaces in an efficient manner.

• `addRange(int left, int right)` Adds the half-open interval `[left, right)`, tracking every real number in that interval. Adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval `[left, right)` that are not already tracked.
• `queryRange(int left, int right)` Returns true if and only if every real number in the interval `[left, right)` is currently being tracked.
• `removeRange(int left, int right)` Stops tracking every real number currently being tracked in the interval `[left, right)`.

Example 1:

``````addRange(10, 20): null
removeRange(14, 16): null
queryRange(10, 14): true (Every number in [10, 14) is being tracked)
queryRange(13, 15): false (Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked)
queryRange(16, 17): true (The number 16 in [16, 17) is still being tracked, despite the remove operation)
``````

Note:

• A half open interval `[left, right)` denotes all real numbers `left <= x < right`.
• `0 < left < right < 10^9` in all calls to `addRange, queryRange, removeRange`.
• The total number of calls to `addRange` in a single test case is at most `1000`.
• The total number of calls to `queryRange` in a single test case is at most `5000`.
• The total number of calls to `removeRange` in a single test case is at most `1000`.

## 题目大意 #

Range 模块是跟踪数字范围的模块。你的任务是以一种有效的方式设计和实现以下接口。

• addRange(int left, int right) 添加半开区间 [left, right)，跟踪该区间中的每个实数。添加与当前跟踪的数字部分重叠的区间时，应当添加在区间 [left, right) 中尚未跟踪的任何数字到该区间中。
• queryRange(int left, int right) 只有在当前正在跟踪区间 [left, right) 中的每一个实数时，才返回 true。
• removeRange(int left, int right) 停止跟踪区间 [left, right) 中当前正在跟踪的每个实数。

``````addRange(10, 20): null
removeRange(14, 16): null
queryRange(10, 14): true （区间 [10, 14) 中的每个数都正在被跟踪）
queryRange(13, 15): false （未跟踪区间 [13, 15) 中像 14, 14.03, 14.17 这样的数字）
queryRange(16, 17): true （尽管执行了删除操作，区间 [16, 17) 中的数字 16 仍然会被跟踪）
``````

• 半开区间 [left, right) 表示所有满足 left <= x < right 的实数。
• 对 addRange, queryRange, removeRange 的所有调用中 0 < left < right < 10^9。
• 在单个测试用例中，对 addRange 的调用总数不超过 1000 次。
• 在单个测试用例中，对  queryRange 的调用总数不超过 5000 次。
• 在单个测试用例中，对 removeRange 的调用总数不超过 1000 次。

## 解题思路 #

• 设计一个数据结构，能完成添加区间 `addRange`，查询区间 `queryRange`，移除区间 `removeRange` 三种操作。查询区间的操作需要更加高效一点。
• 这一题可以用线段树来解答，但是时间复杂度不高，最优解是用二叉排序树 BST 来解答。先来看线段树。这一题是更新区间内的值，所以需要用到懒惰更新。添加区间可以把区间内的值都赋值为 1 。由于题目中未预先确定区间范围，选用树的形式实现线段树比数组实现更加节约空间(当然用数组也可以，区间最大是 1000，点至多有 2000 个)。移除区间的时候就是把区间内的值都赋值标记为 0 。
• 类似的题目有：第 699 题，第 218 题，第 732 题。第 715 题是区间更新定值(不是增减)，第 218 题可以用扫描线，第 732 题和第 699 题类似，也是俄罗斯方块的题目，但是第 732 题的俄罗斯方块的方块会“断裂”。

## 代码 #

``````
package leetcode

// RangeModule define
type RangeModule struct {
Root *SegmentTreeNode
}

// SegmentTreeNode define
type SegmentTreeNode struct {
Start, End  int
Tracked     bool
Lazy        int
Left, Right *SegmentTreeNode
}

// Constructor715 define
func Constructor715() RangeModule {
return RangeModule{&SegmentTreeNode{0, 1e9, false, 0, nil, nil}}
}

func (rm *RangeModule) AddRange(left int, right int) {
update(rm.Root, left, right-1, true)
}

// QueryRange define
func (rm *RangeModule) QueryRange(left int, right int) bool {
return query(rm.Root, left, right-1)
}

// RemoveRange define
func (rm *RangeModule) RemoveRange(left int, right int) {
update(rm.Root, left, right-1, false)
}

func lazyUpdate(node *SegmentTreeNode) {
if node.Lazy != 0 {
node.Tracked = node.Lazy == 2
}
if node.Start != node.End {
if node.Left == nil || node.Right == nil {
m := node.Start + (node.End-node.Start)/2
node.Left = &SegmentTreeNode{node.Start, m, node.Tracked, 0, nil, nil}
node.Right = &SegmentTreeNode{m + 1, node.End, node.Tracked, 0, nil, nil}
} else if node.Lazy != 0 {
node.Left.Lazy = node.Lazy
node.Right.Lazy = node.Lazy
}
}
node.Lazy = 0
}

func update(node *SegmentTreeNode, start, end int, track bool) {
lazyUpdate(node)
if start > end || node == nil || end < node.Start || node.End < start {
return
}
if start <= node.Start && node.End <= end {
// segment completely covered by the update range
node.Tracked = track
if node.Start != node.End {
if track {
node.Left.Lazy = 2
node.Right.Lazy = 2
} else {
node.Left.Lazy = 1
node.Right.Lazy = 1
}
}
return
}
update(node.Left, start, end, track)
update(node.Right, start, end, track)
node.Tracked = node.Left.Tracked && node.Right.Tracked
}

func query(node *SegmentTreeNode, start, end int) bool {
lazyUpdate(node)
if start > end || node == nil || end < node.Start || node.End < start {
return true
}
if start <= node.Start && node.End <= end {
// segment completely covered by the update range
return node.Tracked
}
return query(node.Left, start, end) && query(node.Right, start, end)
}

// 解法二 BST
// type RangeModule struct {
// 	Root *BSTNode
// }

// type BSTNode struct {
// 	Interval    []int
// 	Left, Right *BSTNode
// }

// func Constructor715() RangeModule {
// 	return RangeModule{}
// }

// func (this *RangeModule) AddRange(left int, right int) {
// 	interval := []int{left, right - 1}
// 	this.Root = insert(this.Root, interval)
// }

// func (this *RangeModule) RemoveRange(left int, right int) {
// 	interval := []int{left, right - 1}
// 	this.Root = delete(this.Root, interval)
// }

// func (this *RangeModule) QueryRange(left int, right int) bool {
// 	return query(this.Root, []int{left, right - 1})
// }

// func (this *RangeModule) insert(root *BSTNode, interval []int) *BSTNode {
// 	if root == nil {
// 		return &BSTNode{interval, nil, nil}
// 	}
// 	if root.Interval[0] <= interval[0] && interval[1] <= root.Interval[1] {
// 		return root
// 	}
// 	if interval[0] < root.Interval[0] {
// 		root.Left = insert(root.Left, []int{interval[0], min(interval[1], root.Interval[0]-1)})
// 	}
// 	if root.Interval[1] < interval[1] {
// 		root.Right = insert(root.Right, []int{max(interval[0], root.Interval[1]+1), interval[1]})
// 	}
// 	return root
// }

// func (this *RangeModule) delete(root *BSTNode, interval []int) *BSTNode {
// 	if root == nil {
// 		return nil
// 	}
// 	if interval[0] < root.Interval[0] {
// 		root.Left = delete(root.Left, []int{interval[0], min(interval[1], root.Interval[0]-1)})
// 	}
// 	if root.Interval[1] < interval[1] {
// 		root.Right = delete(root.Right, []int{max(interval[0], root.Interval[1]+1), interval[1]})
// 	}
// 	if interval[1] < root.Interval[0] || root.Interval[1] < interval[0] {
// 		return root
// 	}
// 	if interval[0] <= root.Interval[0] && root.Interval[1] <= interval[1] {
// 		if root.Left == nil {
// 			return root.Right
// 		} else if root.Right == nil {
// 			return root.Left
// 		} else {
// 			pred := root.Left
// 			for pred.Right != nil {
// 				pred = pred.Right
// 			}
// 			root.Interval = pred.Interval
// 			root.Left = delete(root.Left, pred.Interval)
// 			return root
// 		}
// 	}
// 	if root.Interval[0] < interval[0] && interval[1] < root.Interval[1] {
// 		left := &BSTNode{[]int{root.Interval[0], interval[0] - 1}, root.Left, nil}
// 		right := &BSTNode{[]int{interval[1] + 1, root.Interval[1]}, nil, root.Right}
// 		left.Right = right
// 		return left
// 	}
// 	if interval[0] <= root.Interval[0] {
// 		root.Interval[0] = interval[1] + 1
// 	}
// 	if root.Interval[1] <= interval[1] {
// 		root.Interval[1] = interval[0] - 1
// 	}
// 	return root
// }

// func (this *RangeModule) query(root *BSTNode, interval []int) bool {
// 	if root == nil {
// 		return false
// 	}
// 	if interval[1] < root.Interval[0] {
// 		return query(root.Left, interval)
// 	}
// 	if root.Interval[1] < interval[0] {
// 		return query(root.Right, interval)
// 	}
// 	left := true
// 	if interval[0] < root.Interval[0] {
// 		left = query(root.Left, []int{interval[0], root.Interval[0] - 1})
// 	}
// 	right := true
// 	if root.Interval[1] < interval[1] {
// 		right = query(root.Right, []int{root.Interval[1] + 1, interval[1]})
// 	}
// 	return left && right
// }

/**
* Your RangeModule object will be instantiated and called as such:
* obj := Constructor();