Skip to content

Commit 876325b

Browse files
committed
feat: 715. Range Module : 动态开点线段树 / 区间合并
1 parent fd0709e commit 876325b

File tree

4 files changed

+204
-20
lines changed

4 files changed

+204
-20
lines changed

.vscode/settings.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@
115115
"cSpell.words": [
116116
"ACWing",
117117
"Kruskal",
118-
"Manacher",
119-
"SPFA",
120-
"Treap",
121118
"lowbit",
119+
"Manacher",
120+
"pushdown",
122121
"readline",
123-
"struct"
122+
"SPFA",
123+
"struct",
124+
"Treap"
124125
],
125126
// 好多地方只支持 4 的 indent,例如知乎和 AcWing
126127
"markdownlint.config": {
@@ -138,23 +139,23 @@
138139
// prettier is included by eslint
139140
"[javascript]": {
140141
"editor.formatOnSave": false,
141-
"editor.tabSize": 2,
142+
"editor.tabSize": 2
142143
},
143144
"[javascriptreact]": {
144145
"editor.formatOnSave": false,
145-
"editor.tabSize": 2,
146+
"editor.tabSize": 2
146147
},
147148
"[typescript]": {
148149
"editor.formatOnSave": false,
149-
"editor.tabSize": 2,
150+
"editor.tabSize": 2
150151
},
151152
"[typescriptreact]": {
152153
"editor.formatOnSave": false,
153-
"editor.tabSize": 2,
154+
"editor.tabSize": 2
154155
},
155156
"editor.codeActionsOnSave": {
156157
"source.fixAll.eslint": true
157158
},
158159
"eslint.packageManager": "yarn",
159-
"typescript.tsdk": "node_modules\\typescript\\lib",
160+
"typescript.tsdk": "node_modules\\typescript\\lib"
160161
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
class RangeModule {
2+
tree: SegmentTree
3+
constructor () {
4+
this.tree = new SegmentTree(0, 1e9)
5+
}
6+
7+
addRange (left: number, right: number): void {
8+
this.tree.modify(left, right - 1, true)
9+
}
10+
11+
queryRange (left: number, right: number): boolean {
12+
return this.tree.query(left, right - 1) === right - left
13+
}
14+
15+
removeRange (left: number, right: number): void {
16+
this.tree.modify(left, right - 1, false)
17+
}
18+
}
19+
20+
export declare const a: 1
21+
22+
enum Tracked {
23+
TRUE = 'TRUE',
24+
FALSE = 'FALSE'
25+
}
26+
27+
class Node {
28+
start: number
29+
end: number
30+
val: number = 0
31+
lazy: Tracked | null = null
32+
left: null | Node = null
33+
right: null | Node = null
34+
constructor (start: number, end: number) {
35+
this.start = start
36+
this.end = end
37+
}
38+
}
39+
40+
// https://www.acwing.com/activity/content/code/content/167900/
41+
class SegmentTree {
42+
root: Node
43+
constructor (start: number, end: number) {
44+
this.root = new Node(start, end)
45+
}
46+
47+
modify (start: number, end: number, tracked: boolean) {
48+
this.modifyNode(this.root, start, end, tracked)
49+
}
50+
51+
modifyNode (node: Node, start: number, end: number, tracked: boolean) {
52+
if (start <= node.start && end >= node.end) {
53+
node.val = tracked ? (node.end - node.start + 1) : 0
54+
node.lazy = tracked ? Tracked.TRUE : Tracked.FALSE
55+
} else {
56+
this.pushdown(node)
57+
// pushdown 已经确保 left 和 right 一定存在了
58+
if (start <= node.left!.end) this.modifyNode(node.left!, start, end, tracked)
59+
if (end >= node.right!.start) this.modifyNode(node.right!, start, end, tracked)
60+
this.pushup(node)
61+
}
62+
}
63+
64+
pushdown (node: Node) {
65+
const mid = node.start + node.end >> 1
66+
node.left ??= new Node(node.start, mid)
67+
node.right ??= new Node(mid + 1, node.end)
68+
if (node.lazy) {
69+
node.left.lazy = node.lazy
70+
node.left.val = (node.lazy === Tracked.TRUE) ? (node.left.end - node.left.start + 1) : 0
71+
72+
node.right.lazy = node.lazy
73+
node.right.val = (node.lazy === Tracked.TRUE) ? (node.right.end - node.right.start + 1) : 0
74+
75+
node.lazy = null
76+
}
77+
}
78+
79+
pushup (node: Node) {
80+
node.val = node.left!.val + node.right!.val
81+
}
82+
83+
query (start: number, end: number) {
84+
return this.queryNode(this.root, start, end)
85+
}
86+
87+
queryNode (node: Node, start: number, end: number) {
88+
if (start <= node.start && end >= node.end) return node.val
89+
90+
this.pushdown(node)
91+
let sum = 0
92+
if (start <= node.left!.end) sum += this.queryNode(node.left!, start, end)
93+
if (end >= node.right!.start) sum += this.queryNode(node.right!, start, end)
94+
return sum
95+
}
96+
}

leetcode/残酷刷题/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
- [括号匹配](#括号匹配)
3838
- [分治 (Divide and Conquer)](#分治-divide-and-conquer)
3939
- [扫描线 (Sweep Line)](#扫描线-sweep-line)
40+
- [线段树](#线段树)
4041
- [Links](#links)
4142

4243
## Problems
@@ -277,6 +278,10 @@
277278
- 56. Merge Intervals
278279
- 218. The Skyline Problem
279280

281+
## 线段树
282+
283+
- 715. Range Module
284+
280285
## Links
281286

282287
- https://wisdompeak.github.io/lc-score-board/

template-typescript.md

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
> 为了训练自己的 JavaScript/TypeScript 编程能力,能用 TS 写的地方尽量用,不行再换 C++
44
55
- [算法模板(JS/TS 版本)](#算法模板jsts-版本)
6-
- [输入](#输入)
7-
- [`readline` 输入](#readline-输入)
8-
- [`process.stdin.on` 输入](#processstdinon-输入)
9-
- [fs 输入](#fs-输入)
10-
- [常用函数缩写](#常用函数缩写)
11-
- [快速幂](#快速幂)
12-
- [邻接表](#邻接表)
13-
- [快速幂](#快速幂-1)
14-
- [并查集](#并查集)
15-
- [拓扑排序](#拓扑排序)
16-
- [字符串哈希](#字符串哈希)
6+
- [输入](#输入)
7+
- [`readline` 输入](#readline-输入)
8+
- [`process.stdin.on` 输入](#processstdinon-输入)
9+
- [fs 输入](#fs-输入)
10+
- [常用函数缩写](#常用函数缩写)
11+
- [快速幂](#快速幂)
12+
- [邻接表](#邻接表)
13+
- [快速幂](#快速幂-1)
14+
- [并查集](#并查集)
15+
- [拓扑排序](#拓扑排序)
16+
- [字符串哈希](#字符串哈希)
17+
- [线段树](#线段树)
1718

1819
## 输入
1920

@@ -261,3 +262,84 @@ const hash = (i, j) => {
261262
return (f[j] - f[i - 1] * p[j - i + 1] % Q + Q) % Q
262263
}
263264
```
265+
266+
## 线段树
267+
268+
```ts
269+
enum Tracked {
270+
TRUE = 'TRUE',
271+
FALSE = 'FALSE'
272+
}
273+
274+
class Node {
275+
start: number
276+
end: number
277+
val: number = 0
278+
lazy: Tracked | null = null
279+
left: null | Node = null
280+
right: null | Node = null
281+
constructor (start: number, end: number) {
282+
this.start = start
283+
this.end = end
284+
}
285+
}
286+
287+
// https://www.acwing.com/activity/content/code/content/167900/
288+
class SegmentTree {
289+
root: Node
290+
constructor (start: number, end: number) {
291+
this.root = new Node(start, end)
292+
}
293+
294+
modify (start: number, end: number, tracked: boolean) {
295+
this.modifyNode(this.root, start, end, tracked)
296+
}
297+
298+
modifyNode (node: Node, start: number, end: number, tracked: boolean) {
299+
if (start <= node.start && end >= node.end) {
300+
node.val = tracked ? (node.end - node.start + 1) : 0
301+
node.lazy = tracked ? Tracked.TRUE : Tracked.FALSE
302+
} else {
303+
this.pushdown(node)
304+
// pushdown 已经确保 left 和 right 一定存在了
305+
if (start <= node.left!.end) this.modifyNode(node.left!, start, end, tracked)
306+
if (end >= node.right!.start) this.modifyNode(node.right!, start, end, tracked)
307+
this.pushup(node)
308+
}
309+
}
310+
311+
pushdown (node: Node) {
312+
const mid = node.start + node.end >> 1
313+
node.left ??= new Node(node.start, mid)
314+
node.right ??= new Node(mid + 1, node.end)
315+
if (node.lazy) {
316+
node.left.lazy = node.lazy
317+
node.left.val = (node.lazy === Tracked.TRUE) ? (node.left.end - node.left.start + 1) : 0
318+
319+
node.right.lazy = node.lazy
320+
node.right.val = (node.lazy === Tracked.TRUE) ? (node.right.end - node.right.start + 1) : 0
321+
322+
node.lazy = null
323+
}
324+
}
325+
326+
pushup (node: Node) {
327+
node.val = node.left!.val + node.right!.val
328+
}
329+
330+
query (start: number, end: number) {
331+
return this.queryNode(this.root, start, end)
332+
}
333+
334+
queryNode (node: Node, start: number, end: number) {
335+
if (start <= node.start && end >= node.end) return node.val
336+
337+
this.pushdown(node)
338+
let sum = 0
339+
if (start <= node.left!.end) sum += this.queryNode(node.left!, start, end)
340+
if (end >= node.right!.start) sum += this.queryNode(node.right!, start, end)
341+
return sum
342+
}
343+
}
344+
345+
```

0 commit comments

Comments
 (0)