Skip to content

Commit f9e9750

Browse files
authored
Create 3244-shortest-distance-after-road-addition-queries-ii.js
1 parent 911f8df commit f9e9750

File tree

1 file changed

+351
-0
lines changed

1 file changed

+351
-0
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
/**
2+
* @param {number} n
3+
* @param {number[][]} queries
4+
* @return {number[]}
5+
*/
6+
var shortestDistanceAfterQueries = function(n, queries) {
7+
let tree = new SplayTree(), res = [];
8+
for (let i = 0; i < n; i++) tree.insert(i);
9+
for (const [l, r] of queries) {
10+
while (1) {
11+
let pre = tree.higher(l);
12+
if (pre >= r) break;
13+
tree.remove(pre);
14+
}
15+
res.push(tree.size() - 1);
16+
}
17+
return res;
18+
};
19+
20+
///////////////////////// Template //////////////////////////////
21+
class SplayNode {
22+
constructor(value) {
23+
this.parent = null;
24+
this.left = null;
25+
this.right = null;
26+
this.val = value;
27+
this.sum = value;
28+
this.sz = 1;
29+
}
30+
update() {
31+
this.sz = (this.left != null ? this.left.sz : 0) + (this.right != null ? this.right.sz : 0) + 1;
32+
this.sum = (this.left != null ? this.left.sum : 0) + (this.right != null ? this.right.sum : 0) + this.val;
33+
}
34+
isLeft() {
35+
return this.parent != null && this.parent.left == this;
36+
}
37+
isRight() {
38+
return this.parent != null && this.parent.right == this;
39+
}
40+
isRoot(guard = null) {
41+
return this.parent == guard;
42+
}
43+
}
44+
45+
// MultiSet
46+
class SplayTree {
47+
constructor() {
48+
this.root = null;
49+
this.cmp = (x, y) => x >= y ? 0 : 1;
50+
}
51+
zig(x) { // right rotation
52+
let y = x.parent;
53+
if (x.right != null) x.right.parent = y;
54+
y.left = x.right;
55+
x.right = y;
56+
if (y.isLeft()) {
57+
y.parent.left = x;
58+
} else if (y.isRight()) {
59+
y.parent.right = x;
60+
}
61+
x.parent = y.parent;
62+
y.parent = x;
63+
y.update();
64+
x.update();
65+
}
66+
zag(x) { // left rotation
67+
let y = x.parent;
68+
if (x.left != null) x.left.parent = y;
69+
y.right = x.left;
70+
x.left = y;
71+
if (y.isLeft()) {
72+
y.parent.left = x;
73+
} else if (y.isRight()) {
74+
y.parent.right = x;
75+
}
76+
x.parent = y.parent;
77+
y.parent = x;
78+
y.update();
79+
x.update();
80+
}
81+
zigzig(x) { // RR
82+
this.zig(x.parent);
83+
this.zig(x);
84+
}
85+
zigzag(x) { // RL
86+
this.zig(x);
87+
this.zag(x);
88+
}
89+
zagzag(x) { // LL
90+
this.zag(x.parent);
91+
this.zag(x);
92+
}
93+
zagzig(x) { // LR
94+
this.zag(x);
95+
this.zig(x);
96+
}
97+
splay(node, guard = null) { // splay node under guard, default splay to root
98+
while (!node.isRoot(guard)) {
99+
if (node.parent.isRoot(guard)) {
100+
if (node.isLeft()) {
101+
this.zig(node);
102+
} else {
103+
this.zag(node);
104+
}
105+
} else {
106+
if (node.parent.isLeft()) {
107+
if (node.isLeft()) {
108+
this.zigzig(node);
109+
} else {
110+
this.zagzig(node);
111+
}
112+
} else {
113+
if (node.isRight()) {
114+
this.zagzag(node);
115+
} else {
116+
this.zigzag(node);
117+
}
118+
}
119+
}
120+
}
121+
if (guard == null) this.root = node;
122+
}
123+
LastNode(x) {
124+
this.splay(x);
125+
let node = x.left;
126+
if (node == null) return null;
127+
while (node.right != null) node = node.right;
128+
this.splay(node);
129+
return node;
130+
}
131+
NextNode(x) {
132+
this.splay(x);
133+
let node = x.right;
134+
if (node == null) return null;
135+
while (node.left != null) node = node.left;
136+
this.splay(node);
137+
return node;
138+
}
139+
find(value) {
140+
return this.findFirstOf(value);
141+
}
142+
findFirstOf(value) {
143+
let node = this.root, res = null, last_visited = null;
144+
while (node != null) {
145+
last_visited = node;
146+
if (this.cmp(value, node.val)) {
147+
node = node.left;
148+
} else if (this.cmp(node.val, value)) {
149+
node = node.right;
150+
} else {
151+
res = node;
152+
node = node.left;
153+
}
154+
}
155+
if (last_visited != null) this.splay(last_visited);
156+
return res;
157+
}
158+
findLastOf(value) {
159+
let node = this.root, res = null, last_visited = null;
160+
while (node != null) {
161+
last_visited = node;
162+
if (this.cmp(value, node.val)) {
163+
node = node.left;
164+
} else if (this.cmp(node.val, value)) {
165+
node = node.right;
166+
} else {
167+
res = node;
168+
node = node.right;
169+
}
170+
}
171+
if (last_visited != null) this.splay(last_visited);
172+
return res;
173+
}
174+
findRankOf(node) {
175+
this.splay(node);
176+
return node.left == null ? 0 : node.left.sz;
177+
}
178+
findSuccessorOf(value) {
179+
let node = this.root, res = null, last_visited = null;
180+
while (node != null) {
181+
last_visited = node;
182+
if (this.cmp(value, node.val)) {
183+
res = node;
184+
node = node.left;
185+
} else {
186+
node = node.right;
187+
}
188+
}
189+
if (last_visited != null) this.splay(last_visited);
190+
return res;
191+
}
192+
findPrecursorOf(value) {
193+
let node = this.root, res = null, last_visited = null;
194+
while (node != null) {
195+
last_visited = node;
196+
if (this.cmp(node.val, value)) {
197+
res = node;
198+
node = node.right;
199+
} else {
200+
node = node.left;
201+
}
202+
}
203+
if (last_visited != null) this.splay(last_visited);
204+
return res;
205+
}
206+
findKthNode(rank) {
207+
if (rank < 0 || rank >= this.size()) return null;
208+
let node = this.root;
209+
while (node != null) {
210+
let leftsize = node.left == null ? 0 : node.left.sz;
211+
if (leftsize == rank) break;
212+
if (leftsize > rank) {
213+
node = node.left;
214+
} else {
215+
rank -= leftsize + 1;
216+
node = node.right;
217+
}
218+
}
219+
this.splay(node);
220+
return node;
221+
}
222+
make(value) {
223+
return new SplayNode(value);
224+
}
225+
removeNode(node) {
226+
node = null;
227+
}
228+
229+
// -------------------------------- Public Usage --------------------------------------
230+
insert(value) { // allow duplicates LST.set()
231+
if (this.root == null) {
232+
this.root = this.make(value);
233+
return this.root;
234+
}
235+
let node = this.root;
236+
while (node != null) {
237+
if (this.cmp(value, node.val)) {
238+
if (node.left == null) {
239+
node.left = this.make(value);
240+
node.left.parent = node;
241+
node = node.left;
242+
break;
243+
}
244+
node = node.left;
245+
} else {
246+
if (node.right == null) {
247+
node.right = this.make(value);
248+
node.right.parent = node;
249+
node = node.right;
250+
break;
251+
}
252+
node = node.right;
253+
}
254+
}
255+
this.splay(node);
256+
return node;
257+
}
258+
remove(value) { // remove one node, not all LST.unset()
259+
let node = this.find(value);
260+
if (node == null) return false;
261+
this.splay(node);
262+
if (node.left == null) {
263+
this.root = node.right;
264+
if (node.right != null) node.right.parent = null;
265+
this.removeNode(node);
266+
return true;
267+
}
268+
if (node.right == null) {
269+
this.root = node.left;
270+
if (node.left != null) node.left.parent = null;
271+
this.removeNode(node);
272+
return true;
273+
}
274+
let last_node = this.LastNode(node);
275+
let next_node = this.NextNode(node);
276+
this.splay(last_node);
277+
this.splay(next_node, last_node);
278+
this.removeNode(next_node.left);
279+
next_node.left = null;
280+
next_node.update();
281+
last_node.update();
282+
return true;
283+
}
284+
has(value) { // LST.get()
285+
return this.count(value) > 0;
286+
}
287+
count(value) {
288+
let x = this.findFirstOf(value);
289+
if (x == null) return 0;
290+
let rank_x = this.findRankOf(x);
291+
let y = this.findLastOf(value);
292+
let rank_y = this.findRankOf(y);
293+
return rank_y - rank_x + 1;
294+
}
295+
rankOf(value) { // The number of elements strictly less than value
296+
let x = this.findPrecursorOf(value);
297+
return x == null ? 0 : this.findRankOf(x) + 1;
298+
}
299+
findKth(rank) { // (0-indexed)
300+
let x = this.findKthNode(rank);
301+
return x == null ? null : (x.val);
302+
}
303+
higher(value) { // > upper_bound()
304+
let node = this.findSuccessorOf(value);
305+
return node == null ? null : (node.val);
306+
}
307+
lower(value) { // <
308+
let node = this.findPrecursorOf(value);
309+
return node == null ? null : (node.val);
310+
}
311+
ceiling(value) { // >= lower_bound() LST.next(value)
312+
return this.has(value) ? value : this.higher(value);
313+
}
314+
floor(value) { // <= LST.prev(value)
315+
return this.has(value) ? value : this.lower(value);
316+
}
317+
first() {
318+
return this.findKth(0);
319+
}
320+
last() {
321+
return this.findKth(this.size() - 1);
322+
}
323+
poll() {
324+
let res = this.first();
325+
this.remove(res);
326+
return res;
327+
}
328+
pollLast() {
329+
let res = this.last();
330+
this.remove(res);
331+
return res;
332+
}
333+
size() {
334+
return this.root == null ? 0 : this.root.sz;
335+
}
336+
isEmpty() {
337+
return this.root == null;
338+
}
339+
show() {
340+
let res = [];
341+
const dfs = (x) => {
342+
if (x == null) return;
343+
dfs(x.left);
344+
res.push(x.val);
345+
dfs(x.right);
346+
};
347+
dfs(this.root);
348+
return res;
349+
}
350+
}
351+

0 commit comments

Comments
 (0)