@@ -69,21 +69,21 @@ myCalendarThree.book(25, 55); // 返回 3
6969
7070### 方法一:线段树
7171
72- 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $log(width)$。更新某个元素的值,只需要更新 $log(width)$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
72+ 线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $log(\text{ width} )$。更新某个元素的值,只需要更新 $log(\text{ width} )$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用** 懒标记** 保证效率。
7373
7474- 线段树的每个节点代表一个区间;
7575- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $[ 1,N] $;
7676- 线段树的每个叶子节点代表一个长度为 $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⌋$ (即向下取整)。
7878
7979对于本题,线段树节点维护的信息有:
8080
81811 . 区间范围内被预定的次数的最大值 $v$
82- 1 . 懒标记 $add$
82+ 1 . 懒标记 $\text{ add} $
8383
8484由于时间范围为 $10^9$,非常大,因此我们采用动态开点。
8585
86- 时间复杂度 $O(nlogn )$,其中 $n$ 表示日程安排的数量。
86+ 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n )$,其中 $n$ 表示日程安排的数量。
8787
8888<!-- tabs:start -->
8989
@@ -105,7 +105,7 @@ class SegmentTree:
105105 def __init__ (self ):
106106 self .root = Node(1 , int (1e9 + 1 ))
107107
108- def modify (self , l , r , v , node = None ):
108+ def modify (self , l : int , r : int , v : int , node : Node = None ):
109109 if l > r:
110110 return
111111 if node is None :
@@ -121,7 +121,7 @@ class SegmentTree:
121121 self .modify(l, r, v, node.right)
122122 self .pushup(node)
123123
124- def query (self , l , r , node = None ):
124+ def query (self , l : int , r : int , node : Node = None ) -> int :
125125 if l > r:
126126 return 0
127127 if node is None :
@@ -136,10 +136,10 @@ class SegmentTree:
136136 v = max (v, self .query(l, r, node.right))
137137 return v
138138
139- def pushup (self , node ):
139+ def pushup (self , node : Node ):
140140 node.v = max (node.left.v, node.right.v)
141141
142- def pushdown (self , node ):
142+ def pushdown (self , node : Node ):
143143 if node.left is None :
144144 node.left = Node(node.l, node.mid)
145145 if node.right is None :
@@ -312,15 +312,21 @@ public:
312312 }
313313
314314 void modify (int l, int r, int v, Node* node) {
315- if (l > r) return;
315+ if (l > r) {
316+ return;
317+ }
316318 if (node->l >= l && node->r <= r) {
317319 node->v += v;
318320 node->add += v;
319321 return;
320322 }
321323 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+ }
324330 pushup(node);
325331 }
326332
@@ -329,12 +335,18 @@ public:
329335 }
330336
331337 int query(int l, int r, Node* node) {
332- if (l > r) return 0;
338+ if (l > r) {
339+ return 0;
340+ }
333341 if (node->l >= l && node->r <= r) return node->v;
334342 pushdown(node);
335343 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+ }
338350 return v;
339351 }
340352
@@ -343,8 +355,12 @@ public:
343355 }
344356
345357 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+ }
348364 if (node->add) {
349365 Node* left = node->left;
350366 Node* right = node->right;
@@ -483,6 +499,110 @@ func (this *MyCalendarThree) Book(start int, end int) int {
483499 */
484500```
485501
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+
486606<!-- tabs:end -->
487607
488608<!-- solution:end -->
0 commit comments