Skip to content

Commit 17ae684

Browse files
committed
feat: 2286. Booking Concert Tickets in Groups : 线段树
1 parent 096c152 commit 17ae684

File tree

4 files changed

+363
-14
lines changed

4 files changed

+363
-14
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
- [yxc的B站](https://space.bilibili.com/7836741/)
4545
- [残酷刷题群排行榜](https://wisdompeak.github.io/lc-score-board/)[残酷刷题群题目清单](https://docs.google.com/spreadsheets/d/1kBGyRsSdbGDu7DzjQcC-UkZjZERdrP8-_QyVGXHSrB8/edit)[wisdompeak的B站](https://space.bilibili.com/695330558/)
4646
- [群友YoungForest的博客](https://youngforest.github.io/)
47+
- [灵神的模板库 codeforces-go](https://github.com/EndlessCheng/codeforces-go)
4748
- [群友Bill0412的博客](https://kickstart.best/)
4849
- [OTTFF的B站](https://space.bilibili.com/97228279/)
4950
- [zerotrac的B站](https://space.bilibili.com/3203291/)
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
class BookMyShow {
2+
// 每一行剩余的座椅数目
3+
seats: number[]
4+
// 当前仍有座位剩余的最小行号
5+
p: number
6+
tree: SegmentTree
7+
m: number
8+
constructor (n: number, m: number) {
9+
this.m = m
10+
this.seats = Array(n).fill(m)
11+
this.p = 0
12+
this.tree = new SegmentTree(0, n)
13+
// 初始情况,每个节点都有 m 个座位
14+
for (let i = 0; i < n; i++) {
15+
this.tree.modify(i, m)
16+
}
17+
}
18+
19+
gather (k: number, maxRow: number): number[] {
20+
let l = 0; let r = maxRow
21+
while (l < r) {
22+
const mid = l + r >> 1
23+
const [max, sum] = this.tree.query(0, mid)
24+
if (max >= k) r = mid
25+
else l = mid + 1
26+
}
27+
const [max, sum] = this.tree.query(0, l)
28+
if (max < k) return []
29+
this.seats[l] -= k
30+
// 使用 modify 和 modifyRange 是等价的,modifyRange 更加通用
31+
// this.tree.modify(l, this.seats[l])
32+
this.tree.modifyRange(l, l, this.seats[l])
33+
return [l, this.m - this.seats[l] - k]
34+
}
35+
36+
scatter (k: number, maxRow: number): boolean {
37+
const [max, sum] = this.tree.query(0, maxRow)
38+
if (sum < k) return false
39+
while (k) {
40+
const t = Math.min(this.seats[this.p], k)
41+
k -= t
42+
this.seats[this.p] -= t
43+
// this.tree.modify(this.p, this.seats[this.p])
44+
this.tree.modifyRange(this.p, this.p, this.seats[this.p])
45+
if (this.seats[this.p] === 0) this.p++
46+
}
47+
return true
48+
}
49+
}
50+
51+
/**
52+
* Your BookMyShow object will be instantiated and called as such:
53+
* var obj = new BookMyShow(n, m)
54+
* var param_1 = obj.gather(k,maxRow)
55+
* var param_2 = obj.scatter(k,maxRow)
56+
*/
57+
58+
export declare const a: 1
59+
60+
class Node {
61+
start: number
62+
end: number
63+
max: number = 0
64+
sum: number = 0
65+
lazy: number | null = null
66+
left: null | Node = null
67+
right: null | Node = null
68+
constructor (start: number, end: number) {
69+
this.start = start
70+
this.end = end
71+
}
72+
}
73+
74+
// https://www.acwing.com/activity/content/code/content/167900/
75+
class SegmentTree {
76+
root: Node
77+
constructor (start: number, end: number) {
78+
this.root = new Node(start, end)
79+
}
80+
81+
modify (pos: number, val: number) {
82+
this.modifyNode(this.root, pos, val)
83+
}
84+
85+
modifyNode (node: Node, pos: number, val: number) {
86+
if (node.start === pos && node.end === pos) {
87+
node.max = node.sum = val
88+
} else {
89+
this.pushdown(node)
90+
if (pos <= node.left!.end) this.modifyNode(node.left!, pos, val)
91+
if (pos >= node.right!.start) this.modifyNode(node.right!, pos, val)
92+
this.pushup(node)
93+
}
94+
}
95+
96+
// 使用 modify 和 modifyRange 是等价的,modifyRange 更加通用
97+
modifyRange (start: number, end: number, val: number) {
98+
this.modifyNodeRange(this.root, start, end, val)
99+
}
100+
101+
modifyNodeRange (node: Node, start: number, end: number, val: number) {
102+
if (start <= node.start && end >= node.end) {
103+
node.sum = val * (end - start + 1)
104+
node.max = val
105+
node.lazy = val
106+
} else {
107+
this.pushdown(node)
108+
if (start <= node.left!.end) this.modifyNodeRange(node.left!, start, end, val)
109+
if (end >= node.right!.start) this.modifyNodeRange(node.right!, start, end, val)
110+
this.pushup(node)
111+
}
112+
}
113+
114+
// 这里 pushdown 的作用只是动态创建新节点
115+
pushdown (node: Node) {
116+
const mid = node.start + node.end >> 1
117+
node.left ??= new Node(node.start, mid)
118+
node.right ??= new Node(mid + 1, node.end)
119+
if (node.lazy != null) {
120+
node.left.lazy = node.lazy
121+
node.left.max = node.lazy
122+
node.left.sum = node.lazy * (node.left.end - node.left.start + 1)
123+
124+
node.right.lazy = node.lazy
125+
node.right.max = node.lazy
126+
node.right.sum = node.lazy * (node.right.end - node.right.start + 1)
127+
128+
node.lazy = null
129+
}
130+
}
131+
132+
pushup (node: Node) {
133+
node.max = Math.max(node.left!.max, node.right!.max)
134+
node.sum = node.left!.sum + node.right!.sum
135+
}
136+
137+
query (start: number, end: number) {
138+
return this.queryNode(this.root, start, end)
139+
}
140+
141+
queryNode (node: Node, start: number, end: number) {
142+
if (start <= node.start && end >= node.end) return [node.max, node.sum]
143+
144+
this.pushdown(node)
145+
let max = 0; let sum = 0
146+
if (start <= node.left!.end) {
147+
const [_m, _s] = this.queryNode(node.left!, start, end)
148+
max = Math.max(max, _m)
149+
sum += _s
150+
}
151+
if (end >= node.right!.start) {
152+
const [_m, _s] = this.queryNode(node.right!, start, end)
153+
max = Math.max(max, _m)
154+
sum += _s
155+
}
156+
return [max, sum]
157+
}
158+
}

leetcode/残酷刷题/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@
282282

283283
- 715. Range Module
284284
- 2213. Longest Substring of One Repeating Character
285+
- 2286. Booking Concert Tickets in Groups
285286

286287
## Links
287288

0 commit comments

Comments
 (0)