Here's what I usually do:
first calculate f[i][j]
, which denotes the 2^j
-th father of node i
. We have
f[i][j] = f[f[i][j - 1]][j - 1]
Now we can get the j-th
father of node i in log(n)
time.
and we need the depth of every node, say h[i]
Above can be done in a simple dfs()
with complexity of O(N*Log(N))
.
then for every query(i, j) asking the LCA of node(i) and node(j), imagine two monkeys getting up in the tree, trying the get to the same node.
- First make them at the same height, then we know they need to get up
a same height to meet.
- While they're not at the same node, climb as much as possible.
- The father of the node they are currently at is the LCA.
you may refer to this:
int query(int u, int v){
if(h[u]>h[v])swap(u,v);
v = getUp(v,h[v]-h[u]);
for(int i=log(n);i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
while(u!=v){
u=f[u][0];
v=f[v][0];
}
return u;
}
Here getUp(i, j)
means find the j-th
father of node i, as we mentioned above, which can be
int nt(int u,int x){
for(int i=log(n);i>=0;i--){
if((1<<i)<=x){
u=f[u][i];
x-=(1<<i);
}
}
return u;
}
so for very query, the complexity is also O(N*Log(N))
.