Skip to content

Commit f15d44f

Browse files
committed
Create rectangle-area-ii.py
1 parent 181099d commit f15d44f

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

Python/rectangle-area-ii.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Time: O(logn)
2+
# Space: O(n)
3+
4+
# We are given a list of (axis-aligned) rectangles.
5+
# Each rectangle[i] = [x1, y1, x2, y2] ,
6+
# where (x1, y1) are the coordinates of the bottom-left corner,
7+
# and (x2, y2) are the coordinates of the top-right corner of
8+
# the ith rectangle.
9+
#
10+
# Find the total area covered by all rectangles in the plane.
11+
# Since the answer may be too large, return it modulo 10^9 + 7.
12+
#
13+
# Example 1:
14+
#
15+
# Input: [[0,0,2,2],[1,0,2,3],[1,0,3,1]]
16+
# Output: 6
17+
# Explanation: As illustrated in the picture.
18+
# Example 2:
19+
#
20+
# Input: [[0,0,1000000000,1000000000]]
21+
# Output: 49
22+
# Explanation: The answer is 10^18 modulo (10^9 + 7),
23+
# which is (10^9)^2 = (-7)^2 = 49.
24+
#
25+
# Note:
26+
# - 1 <= rectangles.length <= 200
27+
# - rectanges[i].length = 4
28+
# - 0 <= rectangles[i][j] <= 10^9
29+
# - The total area covered by all rectangles will never exceed 2^63 - 1 and
30+
# thus will fit in a 64-bit signed integer.
31+
32+
33+
class SegmentTreeNode(object):
34+
def __init__(self, start, end):
35+
self.start, self.end = start, end
36+
self.total = self.count = 0
37+
self._left = self._right = None
38+
39+
def mid(self):
40+
return (self.start+self.end) // 2
41+
42+
def left(self):
43+
self._left = self._left or SegmentTreeNode(self.start, self.mid())
44+
return self._left
45+
46+
def right(self):
47+
self._right = self._right or SegmentTreeNode(self.mid(), self.end)
48+
return self._right
49+
50+
def update(self, X, i, j, val):
51+
if i >= j:
52+
return 0
53+
if self.start == i and self.end == j:
54+
self.count += val
55+
else:
56+
self.left().update(X, i, min(self.mid(), j), val)
57+
self.right().update(X, max(self.mid(), i), j, val)
58+
if self.count > 0:
59+
self.total = X[self.end]-X[self.start]
60+
else:
61+
self.total = self.left().total + self.right().total
62+
return self.total
63+
64+
65+
class Solution(object):
66+
def rectangleArea(self, rectangles):
67+
"""
68+
:type rectangles: List[List[int]]
69+
:rtype: int
70+
"""
71+
OPEN, CLOSE = 1, -1
72+
events = []
73+
X = set()
74+
for x1, y1, x2, y2 in rectangles:
75+
events.append((y1, OPEN, x1, x2))
76+
events.append((y2, CLOSE, x1, x2))
77+
X.add(x1)
78+
X.add(x2)
79+
events.sort()
80+
X = sorted(X)
81+
Xi = {x: i for i, x in enumerate(X)}
82+
83+
st = SegmentTreeNode(0, len(X)-1)
84+
result = 0
85+
cur_x_sum = 0
86+
cur_y = events[0][0]
87+
for y, typ, x1, x2 in events:
88+
result += cur_x_sum * (y-cur_y)
89+
cur_x_sum = st.update(X, Xi[x1], Xi[x2], typ)
90+
cur_y = y
91+
return result % (10**9+7)

0 commit comments

Comments
 (0)