问题描述
小C拿到了一个空集。她准备进行以下操作:将 [l,r] 区间的每个整数添加进集合。
每次操作后,输出当前集合的 mex。定义集合的 mex 为:集合中最小的未出现的非负整数。
测试样例
样例1:
输入:
q = 4,queries = [[1, 3], [7, 8], [0, 5], [3, 6]]
输出:[0, 0, 6, 9]
样例2:
输入:
q = 3,queries = [[0, 2], [3, 4], [6, 10]]
输出:[3, 5, 5]
样例3:
输入:
q = 2,queries = [[2, 5], [7, 9]]
输出:[0, 0]
珂朵莉树介绍
珂朵莉树(Chtholly Tree),也称为“老司机树”(Old Driver Tree),是一种基于平衡树的数据结构,主要用于解决一类特定的区间操作问题。它最初由一位名叫Old Driver的选手在Codeforces比赛中提出,并因其高效性和简洁性而受到关注。
珂朵莉树的核心思想
珂朵莉树的核心思想是将连续的相同值区间合并成一个节点,从而减少操作的复杂度。具体来说,珂朵莉树维护的是一个有序的区间集合,每个区间包含一个起始位置、一个结束位置和一个值。
主要操作
- 初始化:将整个区间初始化为一个或多个节点。
- 分裂(Split):将一个区间在某个位置分裂成两个区间。
- 合并(Merge):将两个相邻且值相同的区间合并成一个区间。
- 区间赋值(Assign):将某个区间内的所有值赋为同一个值。
- 区间操作(如加法、求和等):对某个区间内的所有值进行操作。
适用场景
珂朵莉树特别适用于以下场景:
- 区间赋值操作频繁。
- 区间操作的值域较大,但操作次数相对较少。
复杂度分析
珂朵莉树的时间复杂度依赖于操作的次数和区间的数量。在理想情况下,每次操作的时间复杂度为O(log n),其中n是区间的数量。
示例
假设我们有一个数组 [1, 1, 1, 2, 2, 3, 3, 3],我们可以将其表示为三个区间:
[1, 1, 1]对应值1[2, 2]对应值2[3, 3, 3]对应值3
如果我们需要将区间 [2, 5] 赋值为 4,我们可以先分裂区间 [1, 1, 1] 和 [2, 2],然后将 [2, 2] 和 [3, 3, 3] 合并成一个新的区间 [4, 4, 4, 4]。
完整代码
from sortedcontainers import SortedDict
class ChthollyTree:
def __init__(self):
self.tree = SortedDict()
def add_range(self, l, r):
# 将区间 [l, r] 添加到珂朵莉树中
if l > r:
return
# 找到第一个大于等于 l 的区间
pos = self.tree.bisect_left(l)
if pos > 0 and self.tree.peekitem(pos - 1)[1] >= l:
pos -= 1
# 合并区间
while pos < len(self.tree) and self.tree.peekitem(pos)[0] <= r:
start, end = self.tree.peekitem(pos)
if end >= l:
l = min(l, start)
r = max(r, end)
del self.tree[start]
pos += 1
self.tree[l] = r
def get_mex(self):
# 计算当前的 mex
mex = 0
for start, end in self.tree.items():
if start > mex:
break
if end >= mex:
mex = end + 1
return mex
def solution(q: int, queries: list) -> list:
# 初始化珂朵莉树和mex
chtholly_tree = ChthollyTree()
results = []
for l, r in queries:
# 将区间 [l, r] 内的所有整数添加到珂朵莉树中
chtholly_tree.add_range(l, r)
# 更新mex
mex = chtholly_tree.get_mex()
# 记录当前的mex
results.append(mex)
return results
if __name__ == '__main__':
print(solution(4, [[1, 3], [7, 8], [0, 5], [3, 6]]) == [0, 0, 6, 9])
print(solution(3, [[0, 2], [3, 4], [6, 10]]) == [3, 5, 5])
print(solution(2, [[2, 5], [7, 9]]) == [0, 0])
总结
珂朵莉树是一种高效的数据结构,特别适用于区间赋值和区间操作频繁的场景。它的实现相对简单,但需要对平衡树有一定的理解。如果你在解决某些区间操作问题时遇到困难,可以考虑使用珂朵莉树来优化你的算法。