1
+ import java .util .ArrayList ;
2
+ import java .util .Arrays ;
3
+ import java .util .List ;
4
+ import java .util .Map ;
5
+ import java .util .TreeMap ;
6
+
7
+ public class Solution850 {
8
+ private static final int MOD = (int ) (1e9 + 7 );
9
+
10
+ public int rectangleArea (int [][] rectangles ) {
11
+ int m = 0 ;
12
+ TreeMap <Integer , Integer > mp = new TreeMap <>();
13
+ // for (int[] sq : squares) {
14
+ // mp.put(sq[0], 1);
15
+ // mp.put(sq[0] + sq[2], 1);
16
+ // }
17
+ for (int [] re : rectangles ) {
18
+ mp .put (re [0 ], 1 );
19
+ mp .put (re [2 ], 1 );
20
+ }
21
+ for (Map .Entry <Integer , Integer > p : mp .entrySet ()) p .setValue (m ++);
22
+ int [] A = new int [m ];
23
+ for (Map .Entry <Integer , Integer > p : mp .entrySet ()) A [p .getValue ()] = p .getKey ();
24
+ // 离散化结束
25
+
26
+ // 把正方形的上下边界取出来
27
+ List <int []> vec = new ArrayList <>();
28
+ // for (int[] sq : squares) {
29
+ // vec.add(new int[]{sq[1], mp.get(sq[0]) + 1, mp.get(sq[0] + sq[2]), 1});
30
+ // vec.add(new int[]{sq[1] + sq[2], mp.get(sq[0]) + 1, mp.get(sq[0] + sq[2]), -1});
31
+ // }
32
+ for (int [] re : rectangles ) {
33
+ vec .add (new int []{re [1 ], mp .get (re [0 ]) + 1 , mp .get (re [2 ]), 1 });
34
+ vec .add (new int []{re [3 ], mp .get (re [0 ]) + 1 , mp .get (re [2 ]), -1 });
35
+ }
36
+ vec .sort (Arrays ::compare );
37
+
38
+ // 求总的面积并
39
+ long tot = 0 ;
40
+ LazySegmentTree seg = new LazySegmentTree (m );
41
+ seg .build (A , 1 , 1 , m - 1 );
42
+ for (int i = 0 ; i + 1 < vec .size (); i ++) {
43
+ // 考虑水平线 y = vec[i][0] 和 y = vec[i + 1][0] 之间的情况
44
+ seg .modify (1 , 1 , m - 1 , vec .get (i )[1 ], vec .get (i )[2 ], vec .get (i )[3 ]);
45
+ // 求横截长度
46
+ int len = A [m - 1 ] - A [0 ];
47
+ // 如果最小覆盖数是 0,那么扣掉相应的长度
48
+ if (seg .info [1 ].mn == 0 ) len -= seg .info [1 ].len ;
49
+ // 面积 = 横截长度 * 高度差
50
+ tot += (long ) len * (vec .get (i + 1 )[0 ] - vec .get (i )[0 ]);
51
+ }
52
+ return (int ) (tot % MOD );
53
+ }
54
+
55
+ // 线段树模板,只需要实现 mergeInfo 和 _do,其余都是固定的
56
+ static class LazySegmentTree {
57
+ static class Info {
58
+ // mn:当前节点的最小覆盖数
59
+ // len:满足覆盖数 = 最小覆盖数的 A[i] 之和
60
+ // lazy:加法的懒标记
61
+ int mn , len , lazy ;
62
+
63
+ public Info (int mn , int len , int lazy ) {
64
+ this .mn = mn ;
65
+ this .len = len ;
66
+ this .lazy = lazy ;
67
+ }
68
+ }
69
+
70
+ Info mergeInfo (Info a , Info b ) {
71
+ int mn = Math .min (a .mn , b .mn );
72
+ return new Info (mn , (a .mn == mn ? a .len : 0 ) + (b .mn == mn ? b .len : 0 ), 0 );
73
+ }
74
+
75
+ // 对节点的覆盖数整个增加 qv,只影响 mn,不影响 len
76
+ void _do (int p , int qv ) {
77
+ info [p ].mn += qv ;
78
+ info [p ].lazy += qv ;
79
+ }
80
+
81
+ int n ;
82
+ Info [] info ;
83
+
84
+ public LazySegmentTree (int n ) {
85
+ this .n = n ;
86
+ info = new Info [4 * n ];
87
+ Arrays .fill (info , new Info (0 , 0 , 0 ));
88
+ }
89
+
90
+ void build (int [] A , int p , int l , int r ) {
91
+ if (l == r ) {
92
+ info [p ] = new Info (0 , A [r ] - A [r - 1 ], 0 );
93
+ return ;
94
+ }
95
+ int m = (l + r ) >> 1 ;
96
+ build (A , p << 1 , l , m );
97
+ build (A , p << 1 | 1 , m + 1 , r );
98
+ maintain (p );
99
+ }
100
+
101
+ void maintain (int p ) {
102
+ info [p ] = mergeInfo (info [p << 1 ], info [p << 1 | 1 ]);
103
+ }
104
+
105
+ void spread (int p ) {
106
+ if (info [p ].lazy == 0 ) return ;
107
+ _do (p << 1 , info [p ].lazy );
108
+ _do (p << 1 | 1 , info [p ].lazy );
109
+ info [p ].lazy = 0 ;
110
+ }
111
+
112
+ void modify (int p , int l , int r , int ql , int qr , int qv ) {
113
+ if (ql <= l && r <= qr ) {
114
+ _do (p , qv );
115
+ return ;
116
+ }
117
+ spread (p );
118
+ int m = (l + r ) >> 1 ;
119
+ if (ql <= m ) modify (p << 1 , l , m , ql , qr , qv );
120
+ if (qr > m ) modify (p << 1 | 1 , m + 1 , r , ql , qr , qv );
121
+ maintain (p );
122
+ }
123
+ }
124
+ }
125
+ /*
126
+ 850. 矩形面积 II
127
+ https://leetcode.cn/problems/rectangle-area-ii/description/
128
+
129
+ 给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中 (xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。
130
+ 计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。
131
+ 返回 总面积 。因为答案可能太大,返回 10^9 + 7 的 模 。
132
+ 提示:
133
+ 1 <= rectangles.length <= 200
134
+ rectanges[i].length = 4
135
+ 0 <= xi1, yi1, xi2, yi2 <= 10^9
136
+ xi1 <= xi2
137
+ yi1 <= yi2
138
+ 所有矩阵面积不为 0。
139
+
140
+ 矩形面积并。
141
+ Lazy 线段树 + 扫描线。
142
+ 相似题目: 3454. 分割正方形 II
143
+ https://leetcode.cn/problems/separate-squares-ii/description/
144
+ */
0 commit comments