LeetCode题解(0715):Range模块(Python)

题目:原题链接(困难)

标签:线段树、有序映射

解法时间复杂度空间复杂度执行用时
Ans 1 (Python)每次操作 = O ( l o g K ) O(logK) O(logK)每次操作 = O ( l o g K ) O(logK) O(logK)3036ms (5.71%)
Ans 2 (Python)
Ans 3 (Python)

解法一:

class SegmentTreeForBivalent:
    """二值线段树:区域查询和更新最大值"""

    class _Node:
        """线段树结点"""
        __slots__ = "start", "end", "val", "left", "right"

        def __init__(self, start, end):
            self.start = start  # 左侧边界(包含)
            self.end = end  # 右侧边界(包含)
            self.left = None  # 结点左子结点
            self.right = None  # 结点右子节点
            self.val = False  # 当前结点最小值

    def __init__(self, size):
        """初始化线段树实例"""
        self.root = self._Node(0, size)

    def _update(self, node, pos1, pos2, data):
        """更新数据"""
        # 当前区间正好为当前结点的情况:即不需要继续分裂的情况
        if node.start == pos1 and node.end == pos2:
            node.val = data
            node.left, node.right = None, None

        # 当前区间为当前结点的部分的情况:即需要继续分裂的情况
        else:
            mid = (node.start + node.end) // 2

            # 创建两个子结点
            if node.left is None:
                node.left = self._Node(node.start, mid)
                node.left.val = node.val
            if node.right is None:
                node.right = self._Node(mid + 1, node.end)
                node.right.val = node.val

            # 更新当前结点的子结点
            if pos2 <= mid:
                self._update(node.left, pos1, pos2, data)
            elif pos1 >= mid + 1:
                self._update(node.right, pos1, pos2, data)
            else:
                self._update(node.left, pos1, mid, data)
                self._update(node.right, mid + 1, pos2, data)

            # 更新当前结点的值
            node.val = node.left.val and node.right.val

    def _query(self, node, start, end):
        """查询数据"""

        # 当前区间正好为当前结点的情况:即不需要继续分裂的情况
        if node.start == start and node.end == end:
            return node.val

        # 当前结点没有子结点的情况:即当前结点下所有位置的结果一致的情况
        elif node.left is None and node.right is None:
            return node.val

        # 当前区间为当前结点的部分的情况:即需要继续分裂的情况
        else:
            mid = (node.start + node.end) // 2

            # 查询当前结果的最小值
            if end <= mid:
                return self._query(node.left, start, end)
            elif start >= mid + 1:
                return self._query(node.right, start, end)
            else:
                return self._query(node.left, start, mid) and self._query(node.right, mid + 1, end)

    def query_one(self, query):
        return self._query(self.root, query, query)

    def query_range(self, start, end):
        return self._query(self.root, start, end)

    def update_one(self, query, data):
        self._update(self.root, query, query, data)

    def update_range(self, start, end, data):
        self._update(self.root, start, end, data)


class RangeModule:

    def __init__(self):
        self.tree = SegmentTreeForBivalent(10 ** 9)

    def addRange(self, left: int, right: int) -> None:
        self.tree.update_range(left, right - 1, True)

    def queryRange(self, left: int, right: int) -> bool:
        return self.tree.query_range(left, right - 1)

    def removeRange(self, left: int, right: int) -> None:
        self.tree.update_range(left, right - 1, False)
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页

打赏

长行

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者