# 我们给出了一个(轴对齐的)二维矩形列表 rectangles。 # 对于 rectangle[i] = [xi1, yi1, xi2, yi2],表示第i个矩形的坐标, # (xi1, yi1)是该矩形左下角的坐标, (xi2, yi2)是该矩形右上角的坐标。 # 计算平面中所有 rectangles 所覆盖的总面积。任何被两个或多个矩形覆盖的区域应只计算一次。 # 返回总面积。因为答案可能太大,返回 10^9 + 7 的模。 # 方法一:找出所有重叠的部分,所有图形总面积减去重叠的部分就是总面积def cal_measure(rectangles): sum_all = 0 re0 = rectangles[0] sum_all += (re0[2] - re0[0]) * (re0[3] - re0[1]) # 总面积 if len(rectangles) < 2: return sum_all % (10 ** 9 + 7) for i in range(len(rectangles) - 1): re1 = rectangles[i] for j in range(i + 1, len(rectangles)): duplicate = [] re2 = rectangles[j] sum_all += (re2[2] - re2[0]) * (re2[3] - re2[1]) if re2[0] > re1[0]: duplicate.append(re2[0] - re1[0]) else: duplicate.append(re1[0] - re2[0]) if re2[1] > re1[1]: duplicate.append(re2[1] - re1[1]) else: duplicate.append(re1[1] - re2[1]) if re2[2] > re1[2]: duplicate.append(re1[2]) else: duplicate.append(re2[2]) if re2[3] > re1[3]: duplicate.append(re1[3]) else: duplicate.append(re2[3]) sum_all -= (duplicate[2] - duplicate[0]) * (duplicate[3] - duplicate[1]) return sum_all % (10 ** 9 + 7) # 方法二:将所有给定的矩形的左右边对应的 x 端点提取出来并排序,每个端点可看作是一条竖直的线段(红色),问题转换为求解「由多条竖直线段分割开」的多个矩形的面积总和(黄色)
from more_itertools import pairwise from typing import List MOD = int(1e9 + 7) def rectangleArea(rectangles: List[List[int]]) -> int: xs, ans = set(), 0 for x0, _, x1, _ in rectangles: xs.add(x0) xs.add(x1) # 纵向x轴扫描线 for a, b in pairwise(sorted(xs)): # xs为所有的x轴扫描线 ys = [(y0, y1) for x0, y0, x1, y1 in rectangles if x0 <= a and b <= x1] # 获得a,b扫描线之间的纵向坐标 s = cur = 0 # 横向y轴扫描线 for c, d in sorted(ys, key=lambda x: (x[0], -x[1])): # 按y0升序,按y1降序 if c > cur: s += d - c # 总高度 elif d > cur: s += d - cur cur = max(cur, d) # 记录当前已计算高度 ans = (ans + s * (b - a)) % MOD return ans if __name__ == '__main__': rectangles = [[0, 0, 2, 2], [1, 0, 2, 3], [1, 0, 3, 1]] rectangles2 = [[0, 0, 1000000000, 1000000000]] print(cal_measure(rectangles)) print(cal_measure(rectangles2)) print(rectangleArea(rectangles))