1
# Runtime: 133 ms (Top 41.78%) | Memory: 13.9 MB (Top 70.89%)3
def __init__(self, xs):4
# cnts[v] means that the node's interval is active5
self.cnts = defaultdict(int)6
# total[v] length of active intervals that are contained the node's interval7
self.total = defaultdict(int)10
def update(self, v, tl, tr, l, r, h):11
# node interval [tl,tr] does not overlap with query interval [l,r]14
# node interval is included in the query interval15
if l <= tl and tr <= r:19
self.update(v * 2, tl, tm, l, r, h)20
self.update(v * 2 + 1, tm + 1, tr, l, r, h)21
# node interval is included in the active interval23
self.total[v] = self.xs[tr + 1] - self.xs[tl]25
self.total[v] = self.total[v * 2] + self.total[v * 2 + 1]30
def rectangleArea(self, rectangles):31
# index i means the interval from xs[i] to xs[i+1]32
xs = sorted(set([x for x1, y1, x2, y2 in rectangles for x in [x1, x2]]))33
xs_i = {x: i for i, x in enumerate(xs)}36
for x1, y1, x2, y2 in rectangles:37
L.append([y1, 1, x1, x2])38
L.append([y2, -1, x1, x2])40
cur_y = cur_x_sum = area = 041
for y, open_close, x1, x2 in L:42
area += (y - cur_y) * cur_x_sum44
# one index corresponds to one interval, that's why we use xs_i[x2]-1 instead of xs_i[x2]45
st.update(1, 0, len(xs) - 1, xs_i[x1], xs_i[x2] - 1, open_close)46
cur_x_sum = st.total[1]48
return area % (10**9 + 7)