51
51
52
52
** 方法一:离散化 + 线段树 + 扫描线**
53
53
54
- 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 ` log(width) ` 。更新某个元素的值,只需要更新 ` log(width) ` 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
54
+ 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $ log(width)$ 。更新某个元素的值,只需要更新 $ log(width)$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
55
55
56
56
- 线段树的每个节点代表一个区间;
57
- - 线段树具有唯一的根节点,代表的区间是整个统计范围,如 ` [1, N] ` ;
58
- - 线段树的每个叶子节点代表一个长度为 1 的元区间 ` [x, x] ` ;
59
- - 对于每个内部节点 ` [l, r] ` ,它的左儿子是 ` [l, mid] ` ,右儿子是 ` [mid + 1, r] ` , 其中 ` mid = ⌊(l + r) / 2⌋ ` (即向下取整)。
57
+ - 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $ [ 1, N] $ ;
58
+ - 线段树的每个叶子节点代表一个长度为 1 的元区间 $ [ x, x] $ ;
59
+ - 对于每个内部节点 $ [ l, r] $ ,它的左儿子是 $ [ l, mid] $ ,右儿子是 $ [ mid + 1, r] $ , 其中 $ mid = ⌊(l + r) / 2⌋$ (即向下取整)。
60
60
61
61
对于本题,线段树节点维护的信息有:
62
62
63
- 1 . 区间被覆盖的次数 cnt;
64
- 1 . 区间被覆盖的长度 len。
63
+ 1 . 区间被覆盖的次数 ` cnt ` ;
64
+ 1 . 区间被覆盖的长度 ` len ` 。
65
65
66
66
另外,由于本题利用了扫描线本身的特性,因此,区间修改时,不需要懒标记,也无须进行 pushdown 操作。
67
67
74
74
``` python
75
75
class Node :
76
76
def __init__ (self ):
77
- self .l = 0
78
- self .r = 0
79
- self .cnt = 0
80
- self .length = 0
77
+ self .l = self .r = 0
78
+ self .cnt = self .length = 0
81
79
82
80
83
81
class SegmentTree :
@@ -107,11 +105,13 @@ class SegmentTree:
107
105
108
106
def pushup (self , u ):
109
107
if self .tr[u].cnt:
110
- self .tr[u].length = self .nums[self .tr[u].r + 1 ] - self .nums[self .tr[u].l]
108
+ self .tr[u].length = self .nums[self .tr[u].r + 1 ] - \
109
+ self .nums[self .tr[u].l]
111
110
elif self .tr[u].l == self .tr[u].r:
112
111
self .tr[u].length = 0
113
112
else :
114
- self .tr[u].length = self .tr[u << 1 ].length + self .tr[u << 1 | 1 ].length
113
+ self .tr[u].length = self .tr[u << 1 ].length + \
114
+ self .tr[u << 1 | 1 ].length
115
115
116
116
@ property
117
117
def length (self ):
@@ -125,15 +125,15 @@ class Solution:
125
125
for x1, y1, x2, y2 in rectangles:
126
126
segs.append((x1, y1, y2, 1 ))
127
127
segs.append((x2, y1, y2, - 1 ))
128
- alls.add(y1)
129
- alls.add(y2)
128
+ alls.update([y1, y2])
129
+
130
+ segs.sort()
130
131
alls = sorted (alls)
131
- m = {v: i for i, v in enumerate (alls)}
132
132
tree = SegmentTree(alls)
133
- segs.sort()
133
+ m = {v: i for i, v in enumerate (alls)}
134
134
ans = 0
135
135
for i, (x, y1, y2, k) in enumerate (segs):
136
- if i > 0 :
136
+ if i:
137
137
ans += tree.length * (x - segs[i - 1 ][0 ])
138
138
tree.modify(1 , m[y1], m[y2] - 1 , k)
139
139
ans %= int (1e9 + 7 )
@@ -146,27 +146,24 @@ class Solution:
146
146
147
147
``` java
148
148
class Node {
149
- int l;
150
- int r;
151
- int cnt;
152
- int len;
149
+ int l, r, cnt, length;
153
150
}
154
151
155
152
class SegmentTree {
156
153
private Node [] tr;
157
154
private int [] nums;
158
155
159
156
public SegmentTree (int [] nums ) {
160
- int n = nums. length - 1 ;
161
157
this . nums = nums;
158
+ int n = nums. length - 1 ;
162
159
tr = new Node [n << 2 ];
163
160
for (int i = 0 ; i < tr. length; ++ i) {
164
161
tr[i] = new Node ();
165
162
}
166
163
build(1 , 0 , n - 1 );
167
164
}
168
165
169
- public void build (int u , int l , int r ) {
166
+ private void build (int u , int l , int r ) {
170
167
tr[u]. l = l;
171
168
tr[u]. r = r;
172
169
if (l != r) {
@@ -191,19 +188,19 @@ class SegmentTree {
191
188
pushup(u);
192
189
}
193
190
194
- public int query () {
195
- return tr[1 ]. len;
196
- }
197
-
198
- public void pushup (int u ) {
191
+ private void pushup (int u ) {
199
192
if (tr[u]. cnt > 0 ) {
200
- tr[u]. len = nums[tr[u]. r + 1 ] - nums[tr[u]. l];
193
+ tr[u]. length = nums[tr[u]. r + 1 ] - nums[tr[u]. l];
201
194
} else if (tr[u]. l == tr[u]. r) {
202
- tr[u]. len = 0 ;
195
+ tr[u]. length = 0 ;
203
196
} else {
204
- tr[u]. len = tr[u << 1 ]. len + tr[u << 1 | 1 ]. len ;
197
+ tr[u]. length = tr[u << 1 ]. length + tr[u << 1 | 1 ]. length ;
205
198
}
206
199
}
200
+
201
+ public int query () {
202
+ return tr[1 ]. length;
203
+ }
207
204
}
208
205
209
206
class Solution {
@@ -212,27 +209,29 @@ class Solution {
212
209
public int rectangleArea (int [][] rectangles ) {
213
210
int n = rectangles. length;
214
211
int [][] segs = new int [n << 1 ][4 ];
215
- int idx = 0 ;
212
+ int i = 0 ;
216
213
TreeSet<Integer > ts = new TreeSet<> ();
217
- for (int [] rect : rectangles) {
218
- int x1 = rect [0 ], y1 = rect [1 ], x2 = rect [2 ], y2 = rect [3 ];
219
- segs[idx ++ ] = new int [] {x1, y1, y2, 1 };
220
- segs[idx ++ ] = new int [] {x2, y1, y2, - 1 };
214
+ for (var e : rectangles) {
215
+ int x1 = e [0 ], y1 = e [1 ], x2 = e [2 ], y2 = e [3 ];
216
+ segs[i ++ ] = new int [] {x1, y1, y2, 1 };
217
+ segs[i ++ ] = new int [] {x2, y1, y2, - 1 };
221
218
ts. add(y1);
222
219
ts. add(y2);
223
220
}
224
- Map<Integer , Integer > m = new HashMap<> ();
221
+ Arrays . sort(segs, (a, b) - > a[0 ] - b[0 ]);
222
+ Map<Integer , Integer > m = new HashMap<> (ts. size());
223
+ i = 0 ;
225
224
int [] nums = new int [ts. size()];
226
- idx = 0 ;
227
225
for (int v : ts) {
228
- nums[idx] = v ;
229
- m . put(v, idx ++ ) ;
226
+ m . put(v, i) ;
227
+ nums[i ++ ] = v ;
230
228
}
231
- Arrays . sort(segs, Comparator . comparingInt(a - > a[ 0 ]));
229
+
232
230
SegmentTree tree = new SegmentTree (nums);
233
231
long ans = 0 ;
234
- for (int i = 0 ; i < segs. length; ++ i) {
235
- int x = segs[i][0 ], y1 = segs[i][1 ], y2 = segs[i][2 ], k = segs[i][3 ];
232
+ for (i = 0 ; i < segs. length; ++ i) {
233
+ var e = segs[i];
234
+ int x = e[0 ], y1 = e[1 ], y2 = e[2 ], k = e[3 ];
236
235
if (i > 0 ) {
237
236
ans += (long ) tree. query() * (x - segs[i - 1 ][0 ]);
238
237
}
@@ -249,18 +248,17 @@ class Solution {
249
248
``` cpp
250
249
class Node {
251
250
public:
252
- int l, r, cnt, len ;
251
+ int l, r, cnt, length ;
253
252
};
254
253
255
254
class SegmentTree {
256
- private :
255
+ public :
257
256
vector<Node* > tr;
258
257
vector<int > nums;
259
258
260
- public:
261
259
SegmentTree(vector<int>& nums) {
262
- int n = nums.size() - 1;
263
260
this->nums = nums;
261
+ int n = nums.size() - 1;
264
262
tr.resize(n << 2);
265
263
for (int i = 0; i < tr.size(); ++i) tr[i] = new Node();
266
264
build(1, 0, n - 1);
@@ -288,51 +286,154 @@ public:
288
286
}
289
287
290
288
int query() {
291
- return tr[1]->len ;
289
+ return tr[1]->length ;
292
290
}
293
291
294
292
void pushup(int u) {
295
293
if (tr[u]->cnt)
296
- tr[u]->len = nums[tr[u]->r + 1] - nums[tr[u]->l];
294
+ tr[u]->length = nums[tr[u]->r + 1] - nums[tr[u]->l];
297
295
else if (tr[u]->l == tr[u]->r)
298
- tr[u]->len = 0;
296
+ tr[u]->length = 0;
299
297
else
300
- tr[u]->len = tr[u << 1]->len + tr[u << 1 | 1]->len ;
298
+ tr[u]->length = tr[u << 1]->length + tr[u << 1 | 1]->length ;
301
299
}
302
300
};
303
301
304
302
class Solution {
305
303
public:
304
+ const int mod = 1e9 + 7;
305
+
306
306
int rectangleArea(vector<vector<int>>& rectangles) {
307
307
int n = rectangles.size();
308
- vector<vector<int >> segs;
308
+ vector<vector<int>> segs(n << 1) ;
309
309
set<int> ts;
310
- int mod = 1e9 + 7 ;
311
- for (auto& rect : rectangles) {
312
- int x1 = rect [ 0] , y1 = rect [ 1] , x2 = rect [ 2] , y2 = rect [ 3] ;
313
- segs.push_back( {x1, y1, y2, 1}) ;
314
- segs.push_back( {x2, y1, y2, -1}) ;
310
+ int i = 0 ;
311
+ for (auto& e : rectangles) {
312
+ int x1 = e [0], y1 = e [1], x2 = e [2], y2 = e [3];
313
+ segs[i++] = {x1, y1, y2, 1};
314
+ segs[i++] = {x2, y1, y2, -1};
315
315
ts.insert(y1);
316
316
ts.insert(y2);
317
317
}
318
- unordered_map<int, int> m;
319
- int idx = 0;
320
- for (int v : ts) m[ v] = idx++;
321
318
sort(segs.begin(), segs.end());
319
+ unordered_map<int, int> m;
320
+ i = 0;
321
+ for (int v : ts) m[v] = i++;
322
322
vector<int> nums(ts.begin(), ts.end());
323
323
SegmentTree* tree = new SegmentTree(nums);
324
324
long long ans = 0;
325
325
for (int i = 0; i < segs.size(); ++i) {
326
- int x = segs[ i] [ 0 ] , y1 = segs[ i] [ 1 ] , y2 = segs[ i] [ 2 ] , k = segs[ i] [ 3 ] ;
327
- if (i > 0) ans += (long long)tree->query() * (x - segs[ i - 1] [ 0 ] );
326
+ auto e = segs[i];
327
+ int x = e[0], y1 = e[1], y2 = e[2], k = e[3];
328
+ if (i > 0) ans += (long long) tree->query() * (x - segs[i - 1][0]);
328
329
tree->modify(1, m[y1], m[y2] - 1, k);
329
330
}
330
331
ans %= mod;
331
- return (int)ans;
332
+ return (int) ans;
332
333
}
333
334
};
334
335
```
335
336
337
+ ### **Go**
338
+
339
+ ```go
340
+ func rectangleArea(rectangles [][]int) int {
341
+ var mod int = 1e9 + 7
342
+ segs := [][]int{}
343
+ alls := map[int]bool{}
344
+ for _, e := range rectangles {
345
+ x1, y1, x2, y2 := e[0], e[1], e[2], e[3]
346
+ segs = append(segs, []int{x1, y1, y2, 1})
347
+ segs = append(segs, []int{x2, y1, y2, -1})
348
+ alls[y1] = true
349
+ alls[y2] = true
350
+ }
351
+ nums := []int{}
352
+ for v := range alls {
353
+ nums = append(nums, v)
354
+ }
355
+ sort.Ints(nums)
356
+ sort.Slice(segs, func(i, j int) bool { return segs[i][0] < segs[j][0] })
357
+ m := map[int]int{}
358
+ for i, v := range nums {
359
+ m[v] = i
360
+ }
361
+ tree := newSegmentTree(nums)
362
+ ans := 0
363
+ for i, e := range segs {
364
+ x, y1, y2, k := e[0], e[1], e[2], e[3]
365
+ if i > 0 {
366
+ ans += tree.query() * (x - segs[i-1][0])
367
+ ans %= mod
368
+ }
369
+ tree.modify(1, m[y1], m[y2]-1, k)
370
+ }
371
+ return ans
372
+ }
373
+
374
+ type node struct {
375
+ l int
376
+ r int
377
+ cnt int
378
+ length int
379
+ }
380
+
381
+ type segmentTree struct {
382
+ tr []*node
383
+ nums []int
384
+ }
385
+
386
+ func newSegmentTree(nums []int) *segmentTree {
387
+ n := len(nums) - 1
388
+ tr := make([]*node, n<<2)
389
+ for i := range tr {
390
+ tr[i] = &node{}
391
+ }
392
+ t := &segmentTree{tr, nums}
393
+ t.build(1, 0, n-1)
394
+ return t
395
+ }
396
+
397
+ func (t *segmentTree) build(u, l, r int) {
398
+ t.tr[u].l, t.tr[u].r = l, r
399
+ if l == r {
400
+ return
401
+ }
402
+ mid := (l + r) >> 1
403
+ t.build(u<<1, l, mid)
404
+ t.build(u<<1|1, mid+1, r)
405
+ }
406
+
407
+ func (t *segmentTree) modify(u, l, r, k int) {
408
+ if t.tr[u].l >= l && t.tr[u].r <= r {
409
+ t.tr[u].cnt += k
410
+ } else {
411
+ mid := (t.tr[u].l + t.tr[u].r) >> 1
412
+ if l <= mid {
413
+ t.modify(u<<1, l, r, k)
414
+ }
415
+ if r > mid {
416
+ t.modify(u<<1|1, l, r, k)
417
+ }
418
+ }
419
+ t.pushup(u)
420
+ }
421
+
422
+ func (t *segmentTree) query() int {
423
+ return t.tr[1].length
424
+ }
425
+
426
+ func (t *segmentTree) pushup(u int) {
427
+ if t.tr[u].cnt > 0 {
428
+ t.tr[u].length = t.nums[t.tr[u].r+1] - t.nums[t.tr[u].l]
429
+ } else if t.tr[u].l == t.tr[u].r {
430
+ t.tr[u].length = 0
431
+ } else {
432
+ t.tr[u].length = t.tr[u<<1].length + t.tr[u<<1|1].length
433
+ }
434
+ }
435
+ ```
436
+
336
437
### ** ...**
337
438
338
439
```
0 commit comments