困难题385 小C的mex查询 珂朵莉树 | 豆包MarsCode AI刷题

141 阅读3分钟

问题描述

小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比赛中提出,并因其高效性和简洁性而受到关注。

珂朵莉树的核心思想

珂朵莉树的核心思想是将连续的相同值区间合并成一个节点,从而减少操作的复杂度。具体来说,珂朵莉树维护的是一个有序的区间集合,每个区间包含一个起始位置、一个结束位置和一个值。

主要操作

  1. 初始化:将整个区间初始化为一个或多个节点。
  2. 分裂(Split):将一个区间在某个位置分裂成两个区间。
  3. 合并(Merge):将两个相邻且值相同的区间合并成一个区间。
  4. 区间赋值(Assign):将某个区间内的所有值赋为同一个值。
  5. 区间操作(如加法、求和等):对某个区间内的所有值进行操作。

适用场景

珂朵莉树特别适用于以下场景:

  • 区间赋值操作频繁。
  • 区间操作的值域较大,但操作次数相对较少。

复杂度分析

珂朵莉树的时间复杂度依赖于操作的次数和区间的数量。在理想情况下,每次操作的时间复杂度为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])

总结

珂朵莉树是一种高效的数据结构,特别适用于区间赋值和区间操作频繁的场景。它的实现相对简单,但需要对平衡树有一定的理解。如果你在解决某些区间操作问题时遇到困难,可以考虑使用珂朵莉树来优化你的算法。