-
Notifications
You must be signed in to change notification settings - Fork 524
/
Copy pathlca_rmq_schieber_vishkin.cpp
128 lines (117 loc) · 3.2 KB
/
lca_rmq_schieber_vishkin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <bits/stdc++.h>
using namespace std;
#ifdef _MSC_VER
int __builtin_clz(unsigned x) {
int bit = 31;
while (bit >= 0 && (x & (1 << bit)) == 0)
--bit;
return 31 - bit;
}
#endif
const int MAX_NODES = 200'000;
int parent[MAX_NODES];
unsigned pre_order[MAX_NODES];
unsigned I[MAX_NODES];
int head[MAX_NODES];
unsigned A[MAX_NODES];
unsigned Time;
unsigned lowest_one_bit(unsigned x) {
return x & -x;
}
unsigned highest_one_bit(unsigned x) {
return x ? 1u << (31 - __builtin_clz(x)) : 0;
}
void dfs1(const vector<vector<int>> &tree, int u, int p) {
parent[u] = p;
I[u] = pre_order[u] = Time++;
for (int v : tree[u]) {
if (v == p)
continue;
dfs1(tree, v, u);
if (lowest_one_bit(I[u]) < lowest_one_bit(I[v])) {
I[u] = I[v];
}
}
head[I[u]] = u;
}
void dfs2(const vector<vector<int>> &tree, int u, int p, unsigned up) {
A[u] = up | lowest_one_bit(I[u]);
for (int v : tree[u]) {
if (v == p)
continue;
dfs2(tree, v, u, A[u]);
}
}
// initialization in O(n)
void init_lca(const vector<vector<int>> &tree, int root) {
Time = 0;
dfs1(tree, root, -1);
dfs2(tree, root, -1, 0);
}
int enter_into_strip(int x, int hz) {
if (lowest_one_bit(I[x]) == hz)
return x;
int hw = highest_one_bit(A[x] & (hz - 1));
return parent[head[(I[x] & -hw) | hw]];
}
// lca in O(1)
int lca(int x, int y) {
int hb = I[x] == I[y] ? lowest_one_bit(I[x]) : highest_one_bit(I[x] ^ I[y]);
int hz = lowest_one_bit(A[x] & A[y] & -hb);
int ex = enter_into_strip(x, hz);
int ey = enter_into_strip(y, hz);
return pre_order[ex] < pre_order[ey] ? ex : ey;
}
void init_rmq(const vector<int> &values) {
// build Cartesian Tree
int n = values.size();
int root = 0;
vector<int> p(n, -1);
for (int i = 1; i < n; i++) {
int prev = i - 1;
int next = -1;
while (values[prev] > values[i] && p[prev] != -1) {
next = prev;
prev = p[prev];
}
if (values[prev] > values[i]) {
p[prev] = i;
root = i;
} else {
p[i] = prev;
if (next != -1) {
p[next] = i;
}
}
}
vector<vector<int>> tree(n);
for (int i = 0; i < n; ++i)
if (p[i] != -1)
tree[p[i]].push_back(i);
init_lca(tree, root);
}
// random test
int main() {
mt19937 rng(1);
for (int step = 0; step < 1000; ++step) {
int n = uniform_int_distribution<int>(1, 10)(rng);
vector<int> v(n);
for (int i = 0; i < n; ++i) {
v[i] = uniform_int_distribution<int>(0, 5)(rng);
}
int a = uniform_int_distribution<int>(0, n - 1)(rng);
int b = uniform_int_distribution<int>(0, n - 1)(rng);
if (a > b)
swap(a, b);
init_rmq(v);
int res1 = v[lca(a, b)];
int res2 = *min_element(v.begin() + a, v.begin() + b + 1);
if (res1 != res2) {
for (int i = 0; i < n; ++i)
cout << v[i] << " ";
cout << endl;
cout << a << " " << b << " - " << res1 << " " << res2 << endl;
assert(res1 != res2);
}
}
}