Skip to content

Commit 5635e71

Browse files
committed
LCA in O(logn)
1 parent 952de7c commit 5635e71

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

LeastCommonAncestor.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Deleted code is debugged code :)
3+
*/
4+
#include <bits/stdc++.h>
5+
#define ll long long
6+
#define ull unsigned long long
7+
#define vi vector<ll>
8+
#define pp pair<ll,ll>
9+
#define mp make_pair
10+
#define PI acos(-1.0)
11+
#define all(v) v.begin(),v.end()
12+
#define pb push_back
13+
#define FOR(i,a,b) for(i=a;i<b;i++)
14+
#define FREV(i,a,b) for(i=a;i>=b;i--)
15+
#define SULL(n) scanf("%llu", &n)
16+
#define INF 1e18
17+
#define MOD 1000000007
18+
19+
#ifndef ONLINE_JUDGE
20+
#define gc getchar
21+
#define pc putchar
22+
#else
23+
#define gc getchar_unlocked
24+
#define pc putchar_unlocked
25+
#endif
26+
27+
using namespace std;
28+
29+
int read_int() {
30+
char c = gc();
31+
while((c < '0' || c > '9') && c != '-') c = gc();
32+
int ret = 0, neg = 0;
33+
if (c == '-') neg = 1, c = gc();
34+
while(c >= '0' && c <= '9') {
35+
ret = 10 * ret + c - 48;
36+
c = gc();
37+
}
38+
return neg ? -ret : ret;
39+
}
40+
41+
ll read_ll() {
42+
char c = gc();
43+
while((c < '0' || c > '9') && c != '-') c = gc();
44+
ll ret = 0;
45+
int neg = 0;
46+
if (c == '-') neg = 1, c = gc();
47+
while(c >= '0' && c <= '9') {
48+
ret = 10 * ret + c - 48;
49+
c = gc();
50+
}
51+
return neg ? -ret : ret;
52+
}
53+
54+
/*******************************************RANDOM STUFF BEGINS HERE**************************************************/
55+
56+
struct node {
57+
vi adj;
58+
};
59+
60+
vector<node> tree;
61+
vi depth(100005), parent(100005);
62+
63+
// DFS to calculate depths of the nodes
64+
void dfs(ll u) {
65+
ll i, len = tree[u].adj.size();
66+
FOR(i,0,len) {
67+
ll v = tree[u].adj[i];
68+
depth[v] = depth[u] + 1;
69+
dfs(v);
70+
}
71+
}
72+
73+
// Preprocessing for LCA in O(nlogn)
74+
// binary_ancestor[i][j] stores the 2^j ancestor of node i
75+
76+
ll binary_ancestor[1000005][20];
77+
78+
void LCA_preprocessing(ll n) {
79+
ll i, j;
80+
81+
for(i = 1; i <= n; i++) {
82+
for(j = 0; 1 << j <= n; j++) {
83+
binary_ancestor[i][j] = -1;
84+
}
85+
}
86+
87+
for(i = 1; i <= n; i++) {
88+
binary_ancestor[i][0] = parent[i];
89+
}
90+
91+
for(j = 1; 1 << j <=n; j++) {
92+
for(i = 1; i <= n; i++) {
93+
binary_ancestor[i][j] = binary_ancestor[binary_ancestor[i][j-1]][j-1];
94+
}
95+
}
96+
}
97+
98+
ll getLCA(ll x, ll y) {
99+
ll i, temp, log;
100+
101+
// make x the node with greater depth
102+
if (depth[x] < depth[y]) {
103+
temp = x, x = y, y = temp;
104+
}
105+
106+
for(log = 1; 1 << log <= depth[x]; log++);
107+
log--;
108+
109+
// bring x and y to the same level
110+
for(i = log; i >= 0; i--) {
111+
if (depth[x] - (1 << i) >= depth[y]) {
112+
x = binary_ancestor[x][i];
113+
}
114+
}
115+
116+
// x and y are now at the same level
117+
for(i = log; i >= 0; i--) {
118+
if (binary_ancestor[x][i] != -1 && binary_ancestor[x][i] != binary_ancestor[y][i]) {
119+
x = binary_ancestor[x][i];
120+
y = binary_ancestor[y][i];
121+
}
122+
}
123+
124+
return parent[x];
125+
}
126+
127+
int main() {
128+
ll i,j,t,n,x,y;
129+
n = read_ll();
130+
tree.resize(n+1);
131+
// 1 is the root. Accept parents of the remaining (n-1) nodes
132+
FOR(i,2,n+1) {
133+
j = read_ll();
134+
tree[j].adj.pb(i);
135+
parent[i] = j;
136+
}
137+
dfs(1);
138+
LCA_preprocessing(n);
139+
x = read_ll();
140+
y = read_ll();
141+
cout << "LCA of " << x << " and " << y << " = " << getLCA(x,y) << endl;
142+
return 0;
143+
}

0 commit comments

Comments
 (0)