LC 1851. 包含每个查询的最小区间
https://leetcode-cn.com/problems/minimum-interval-to-include-each-query/
这题和 LC 1847 思路几乎完全一样,我的处理方式也几乎完全一样,写了两个版本,一个是区间树,一个是题解中的事件处理方法。 和 LC 1847 不同的是,区间树的版本居然通过了,给了我比较大的信心,看来还能写代码。
区间树的 代码 依然是没有办法看,但是思路也比较清晰:
- 将这些区间不断地插入到区间树中。
- 插入区间维护好覆盖这个区间的最小size.
- 拿到所有的叶子节点,针对每个query进行二分。
事实证明,在做leetcode的时候如果是要写树的话,基本上思路就错了。
变为基于事件的处理方法是:
- 对每个interval (s, e), 产生两个事件: enter s and exit e
- 对每个query (q), 产生一个事件 do query on q.
- 在遍历事件的时候不断维护有效的区间,然后选择size最小的区间
class Solution:
def minInterval(self, intervals: List[List[int]], queries: List[int]) -> List[int]:
events = []
for i in range(len(intervals)):
(a, b) = intervals[i]
e = (a, 0, i)
events.append(e)
e = (b, 2, i)
events.append(e)
for i in range(len(queries)):
q = queries[i]
e = (q, 1, i)
events.append(e)
events.sort()
from sortedcontainers import SortedList
ls = SortedList()
retired = set()
ans = [-1] * len(queries)
#print(events)
for (_, type, index) in events:
if type == 1: # query
while ls and ls[0][1] in retired:
del ls[0]
size = -1
if ls:
size = ls[0][0]
ans[index] = size
elif type == 0: # enqueue.
size = intervals[index][1] - intervals[index][0] + 1
ls.add((size, index))
else:
retired.add(index)
return ans