class RangeModule(object):
def __init__(self):
# [(1,2),(3,6),(8,12)]
self.ranges = []
def overlap(self, left, right):
i, j = 0, len(self.ranges) - 1
while i < len(self.ranges) and self.ranges[i][1] < left:
i += 1
while j >= 0 and self.ranges[j][0] > right:
j -= 1
return i, j
def addRange(self, left, right):
i, j = self.overlap(left, right)
if i <= j:
left = min(left, self.ranges[i][0])
right = max(right, self.ranges[j][1])
self.ranges[i:j+1] = [(left, right)]
def queryRange(self, left, right):
i = bisect.bisect_right(self.ranges, (left, float('inf'))) - 1
return bool(self.ranges and self.ranges[i][0] <= left and right <= self.ranges[i][1])
def removeRange(self, left, right):
i, j = self.overlap(left, right)
merge = []
for k in xrange(i, j+1):
if self.ranges[k][0] < left:
merge.append((self.ranges[k][0], left))
if right < self.ranges[k][1]:
merge.append((right, self.ranges[k][1]))
self.ranges[i:j+1] = merge
class RangeModule(object):
def __init__(self):
# [1,2,3,5,8,12]
self.ranges = []
def overlap(self, left, right, is_odd):
i = bisect_left(self.ranges, left)
j = bisect_right(self.ranges, right)
merge = []
if i & 1 == int(is_odd):
merge.append(left)
if j & 1 == int(is_odd):
merge.append(right)
# 修改 ranges 的 [i:j-1] 部分
self.ranges[i:j] = merge
def addRange(self, left, right):
# [1,2,3,5,8,12], 代入 left = 3, right = 5,此时需要保持不变, 就不难知道应该用 bisect_left 还是 bisect_right
return self.overlap(left, right, False)
def removeRange(self, left, right):
# [1,2,3,5,8,12], 代入 left = 3, right = 5,此时需要为 [1,2,8,12], 就不难知道应该用 bisect_left 还是 bisect_right
return self.overlap(left, right, True)
def queryRange(self, left, right):
# [1,2,3,5,8,12], 代入 left = 3, right = 5,此时需要返回 true, 就不难知道应该用 bisect_left 还是 bisect_right
i = bisect_right(self.ranges, left)
j = bisect_left(self.ranges, right)
return i & 1 == 1 and i == j # 都在一个区间内
class Node:
def __init__(self, l, r):
self.left = None # 左孩子的指针
self.right = None # 右孩子的指针
self.l = l # 区间左端点
self.r = r # 区间右端点
self.m = (l + r) >> 1 # 中点
self.v = 0 # 当前值
self.add = -1 # 懒标记
class SegmentTree:
def __init__(self,n):
# 默认就一个根节点,不 build 出整个树,节省空间
self.root = Node(0,n-1) # 根节点
def update(self, l, r, v, node):
if l > node.r or r < node.l:
return
if l <= node.l and node.r <= r:
node.v = (node.r - node.l + 1) * v
node.add = v # 做了一个标记
return
self.__pushdown(node) # 动态开点。为子节点赋值,这个值就从 add 传递过来
if l <= node.m:
self.update(l, r, v, node.left)
if r > node.m:
self.update(l, r, v, node.right)
self.__pushup(node) # 动态开点结束后,修复当前节点的值
def query(self, l, r,node):
if l > node.r or r < node.l:
return False
if l <= node.l and node.r <= r:
return node.v == node.r - node.l + 1
self.__pushdown(node) # 动态开点。为子节点赋值,这个值就从 add 传递过来
ans = True
if l <= node.m:
ans = self.query(l, r, node.left)
if ans and r > node.m:
ans = self.query(l, r, node.right)
return ans
def __pushdown(self,node):
if node.left is None:
node.left = Node(node.l, node.m)
if node.right is None:
node.right = Node(node.m + 1, node.r)
if node.add != -1:
node.left.v = (node.left.r - node.left.l + 1) * node.add
node.right.v = (node.right.r - node.right.l + 1) * node.add
node.left.add = node.add
node.right.add = node.add
node.add = -1
def __pushup(self,node):
node.v = node.left.v + node.right.v
def updateSum(self,index,val):
self.update(index,index,val,self.root)
def querySum(self,left,right):
return self.query(left,right,self.root)
class RangeModule:
def __init__(self):
self.tree = SegmentTree(10 ** 9)
def addRange(self, left: int, right: int) -> None:
self.tree.update(left, right - 1, 1, self.tree.root)
def queryRange(self, left: int, right: int) -> bool:
return not not self.tree.querySum(left, right - 1)
def removeRange(self, left: int, right: int) -> None:
self.tree.update(left, right - 1, 0, self.tree.root)
# Your RangeModule object will be instantiated and called as such:
# obj = RangeModule()
# obj.addRange(left,right)
# param_2 = obj.queryRange(left,right)
# obj.removeRange(left,right)