1
from bisect import bisect_left as bl, bisect_right as br9
def addRange(self, left: int, right: int) -> None:11
# If idx(left) or idx(right) is odd, it's in a interval. So don't add it.12
# If idx(left) or idx(right) is even, it's not in any interval. So add it as new interval13
# Slice array[idx(left) : idx(right)]14
# 1) both odd: Nothing is added. Merge all middle intervals.15
# 2) both even: Add new intervals. Merge all middle intervals16
# 3) idx(left) is even: update start point of next interval with left17
# 4) idx(right) is even: update end point of previous interval with right18
# Bisect_left vs. Bisect_right19
# left need to proceed all interval closing at left, so use Bisect_left20
# right need to go after all interval openning at right, so use Bisect_right21
i, j = bl(self._X, left), br(self._X, right)22
self._X[i:j] = [left] * (i % 2 == 0) + [right] * (j % 2 == 0)24
def queryRange(self, left: int, right: int) -> bool:26
# If idx of left/right is odd, it's in a interval. Else it's not.27
# If idx of left&right is the same, they're in the same interval28
# Bisect_left vs. Bisect_right29
# [start, end). Start is included. End is not.30
# so use bisect_right for left31
# so use bisect_left for right32
i, j = br(self._X, left), bl(self._X, right)33
return i == j and i % 2 == 135
def removeRange(self, left: int, right: int) -> None:37
# If idx(left) is odd, the interval that contains left need to change end point to left38
# If idx(right) is odd, the interval that contains right need to change start point to right39
# Else, everything from idx(left) to idx(right) is removed. Nothing is changed.40
# Bisect_left vs. Bisect_right42
i, j = bl(self._X, left), br(self._X, right)43
self._X[i:j] = [left] * (i % 2 == 1) + [right] * (j % 2 == 1)