@@ -69,21 +69,21 @@ myCalendarThree.book(25, 55); // 返回 3
69
69
70
70
### 方法一:线段树
71
71
72
- 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $log(width)$。更新某个元素的值,只需要更新 $log(width)$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
72
+ 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $log(\text{ width} )$。更新某个元素的值,只需要更新 $log(\text{ width} )$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
73
73
74
74
- 线段树的每个节点代表一个区间;
75
75
- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $[ 1,N] $;
76
76
- 线段树的每个叶子节点代表一个长度为 $1$ 的元区间 $[ x, x] $;
77
- - 对于每个内部节点 $[ l,r] $,它的左儿子是 $[ l,mid] $,右儿子是 $[ mid+1,r] $, 其中 $mid = ⌊(l+r)/2⌋$ (即向下取整)。
77
+ - 对于每个内部节点 $[ l,r] $,它的左儿子是 $[ l,\text{ mid} ] $,右儿子是 $[ \text{ mid} +1,r] $, 其中 $\text{ mid} = ⌊(l+r)/2⌋$ (即向下取整)。
78
78
79
79
对于本题,线段树节点维护的信息有:
80
80
81
81
1 . 区间范围内被预定的次数的最大值 $v$
82
- 1 . 懒标记 $add$
82
+ 1 . 懒标记 $\text{ add} $
83
83
84
84
由于时间范围为 $10^9$,非常大,因此我们采用动态开点。
85
85
86
- 时间复杂度 $O(nlogn )$,其中 $n$ 表示日程安排的数量。
86
+ 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n )$,其中 $n$ 表示日程安排的数量。
87
87
88
88
<!-- tabs:start -->
89
89
@@ -105,7 +105,7 @@ class SegmentTree:
105
105
def __init__ (self ):
106
106
self .root = Node(1 , int (1e9 + 1 ))
107
107
108
- def modify (self , l , r , v , node = None ):
108
+ def modify (self , l : int , r : int , v : int , node : Node = None ):
109
109
if l > r:
110
110
return
111
111
if node is None :
@@ -121,7 +121,7 @@ class SegmentTree:
121
121
self .modify(l, r, v, node.right)
122
122
self .pushup(node)
123
123
124
- def query (self , l , r , node = None ):
124
+ def query (self , l : int , r : int , node : Node = None ) -> int :
125
125
if l > r:
126
126
return 0
127
127
if node is None :
@@ -136,10 +136,10 @@ class SegmentTree:
136
136
v = max (v, self .query(l, r, node.right))
137
137
return v
138
138
139
- def pushup (self , node ):
139
+ def pushup (self , node : Node ):
140
140
node.v = max (node.left.v, node.right.v)
141
141
142
- def pushdown (self , node ):
142
+ def pushdown (self , node : Node ):
143
143
if node.left is None :
144
144
node.left = Node(node.l, node.mid)
145
145
if node.right is None :
@@ -312,15 +312,21 @@ public:
312
312
}
313
313
314
314
void modify (int l, int r, int v, Node* node) {
315
- if (l > r) return;
315
+ if (l > r) {
316
+ return;
317
+ }
316
318
if (node->l >= l && node->r <= r) {
317
319
node->v += v;
318
320
node->add += v;
319
321
return;
320
322
}
321
323
pushdown(node);
322
- if (l <= node->mid) modify(l, r, v, node->left);
323
- if (r > node->mid) modify(l, r, v, node->right);
324
+ if (l <= node->mid) {
325
+ modify(l, r, v, node->left);
326
+ }
327
+ if (r > node->mid) {
328
+ modify(l, r, v, node->right);
329
+ }
324
330
pushup(node);
325
331
}
326
332
@@ -329,12 +335,18 @@ public:
329
335
}
330
336
331
337
int query(int l, int r, Node* node) {
332
- if (l > r) return 0;
338
+ if (l > r) {
339
+ return 0;
340
+ }
333
341
if (node->l >= l && node->r <= r) return node->v;
334
342
pushdown(node);
335
343
int v = 0;
336
- if (l <= node->mid) v = max(v, query(l, r, node->left));
337
- if (r > node->mid) v = max(v, query(l, r, node->right));
344
+ if (l <= node->mid) {
345
+ v = max(v, query(l, r, node->left));
346
+ }
347
+ if (r > node->mid) {
348
+ v = max(v, query(l, r, node->right));
349
+ }
338
350
return v;
339
351
}
340
352
@@ -343,8 +355,12 @@ public:
343
355
}
344
356
345
357
void pushdown(Node* node) {
346
- if (!node->left) node->left = new Node(node->l, node->mid);
347
- if (!node->right) node->right = new Node(node->mid + 1, node->r);
358
+ if (!node->left) {
359
+ node->left = new Node(node->l, node->mid);
360
+ }
361
+ if (!node->right) {
362
+ node->right = new Node(node->mid + 1, node->r);
363
+ }
348
364
if (node->add) {
349
365
Node* left = node->left;
350
366
Node* right = node->right;
@@ -483,6 +499,110 @@ func (this *MyCalendarThree) Book(start int, end int) int {
483
499
*/
484
500
```
485
501
502
+ #### TypeScript
503
+
504
+ ``` ts
505
+ class Node {
506
+ left: Node | null = null ;
507
+ right: Node | null = null ;
508
+ l: number ;
509
+ r: number ;
510
+ mid: number ;
511
+ v: number = 0 ;
512
+ add: number = 0 ;
513
+
514
+ constructor (l : number , r : number ) {
515
+ this .l = l ;
516
+ this .r = r ;
517
+ this .mid = (l + r ) >> 1 ;
518
+ }
519
+ }
520
+
521
+ class SegmentTree {
522
+ private root: Node = new Node (1 , 1e9 + 1 );
523
+
524
+ constructor () {}
525
+
526
+ modify(l : number , r : number , v : number , node : Node = this .root ): void {
527
+ if (l > r ) {
528
+ return ;
529
+ }
530
+ if (node .l >= l && node .r <= r ) {
531
+ node .v += v ;
532
+ node .add += v ;
533
+ return ;
534
+ }
535
+ this .pushdown (node );
536
+ if (l <= node .mid ) {
537
+ this .modify (l , r , v , node .left ! );
538
+ }
539
+ if (r > node .mid ) {
540
+ this .modify (l , r , v , node .right ! );
541
+ }
542
+ this .pushup (node );
543
+ }
544
+
545
+ query(l : number , r : number , node : Node = this .root ): number {
546
+ if (l > r ) {
547
+ return 0 ;
548
+ }
549
+ if (node .l >= l && node .r <= r ) {
550
+ return node .v ;
551
+ }
552
+ this .pushdown (node );
553
+ let v = 0 ;
554
+ if (l <= node .mid ) {
555
+ v = Math .max (v , this .query (l , r , node .left ! ));
556
+ }
557
+ if (r > node .mid ) {
558
+ v = Math .max (v , this .query (l , r , node .right ! ));
559
+ }
560
+ return v ;
561
+ }
562
+
563
+ private pushup(node : Node ): void {
564
+ node .v = Math .max (node .left ! .v , node .right ! .v );
565
+ }
566
+
567
+ private pushdown(node : Node ): void {
568
+ if (node .left === null ) {
569
+ node .left = new Node (node .l , node .mid );
570
+ }
571
+ if (node .right === null ) {
572
+ node .right = new Node (node .mid + 1 , node .r );
573
+ }
574
+ if (node .add !== 0 ) {
575
+ const left = node .left ! ;
576
+ const right = node .right ! ;
577
+ left .add += node .add ;
578
+ right .add += node .add ;
579
+ left .v += node .add ;
580
+ right .v += node .add ;
581
+ node .add = 0 ;
582
+ }
583
+ }
584
+ }
585
+
586
+ class MyCalendarThree {
587
+ private tree: SegmentTree ;
588
+
589
+ constructor () {
590
+ this .tree = new SegmentTree ();
591
+ }
592
+
593
+ book(start : number , end : number ): number {
594
+ this .tree .modify (start + 1 , end , 1 );
595
+ return this .tree .query (1 , 1e9 + 1 );
596
+ }
597
+ }
598
+
599
+ /**
600
+ * Your MyCalendarThree object will be instantiated and called as such:
601
+ * var obj = new MyCalendarThree()
602
+ * var param_1 = obj.book(startTime, endTime)
603
+ */
604
+ ```
605
+
486
606
<!-- tabs:end -->
487
607
488
608
<!-- solution:end -->
0 commit comments