using
System;
using
System.Collections.Generic;
public
class
GFG
{
public
class
Pair<T, V>
{
public
T first;
public
V second;
public
Pair() {
}
public
Pair(T first, V second)
{
this
.first = first;
this
.second = second;
}
}
public
class
Node
{
public
int
data;
public
Node left, right;
public
Node(
int
data)
{
this
.data = data;
this
.left =
this
.right =
null
;
}
}
static
int
MAX = 100001;
static
int
[] level =
new
int
[MAX];
static
void
FindLevels(Node root)
{
if
(root ==
null
)
return
;
Queue<Pair<Node,
int
>> q =
new
Queue<Pair<Node,
int
>>();
q.Enqueue(
new
Pair<Node,
int
>(root, 0));
Pair<Node,
int
> p =
new
Pair<Node,
int
>();
while
(q.Count != 0)
{
p = q.Peek();
q.Dequeue();
level[p.first.data] = p.second;
if
(p.first.left !=
null
)
q.Enqueue(
new
Pair<Node,
int
>(p.first.left, p.second + 1));
if
(p.first.right !=
null
)
q.Enqueue(
new
Pair<Node,
int
>(p.first.right, p.second + 1));
}
}
static
int
[] Euler =
new
int
[MAX];
static
int
idx = 0;
static
void
eulerTree(Node root)
{
Euler[++idx] = root.data;
if
(root.left !=
null
)
{
eulerTree(root.left);
Euler[++idx] = root.data;
}
if
(root.right !=
null
)
{
eulerTree(root.right);
Euler[++idx] = root.data;
}
}
static
int
[] vis =
new
int
[MAX];
static
int
[] L =
new
int
[MAX];
static
int
[] H =
new
int
[MAX];
static
void
preprocessEuler(
int
size) {
for
(
int
i = 1; i <= size; i++) {
L[i] = level[Euler[i]];
if
(vis[Euler[i]] == 0)
{
H[Euler[i]] = i;
vis[Euler[i]] = 1;
}
}
}
static
int
[,] M =
new
int
[MAX, 18];
static
void
preprocessLCA(
int
N)
{
for
(
int
i = 0; i < N; i++)
M[i, 0] = i;
for
(
int
j = 1; 1 << j <= N; j++)
for
(
int
i = 0; i + (1 << j) - 1 < N; i++)
if
(L[M[i, j - 1]] < L[M[i + (1 << (j - 1)), j - 1]])
M[i, j] = M[i, j - 1];
else
M[i, j] = M[i + (1 << (j - 1)), j - 1];
}
static
int
LCA(
int
a,
int
b)
{
int
j = (
int
) (Math.Log(b - a + 1) / Math.Log(2));
if
(L[M[a,j]] <= L[M[b - (1 << j) + 1,j]])
return
M[a,j];
else
return
M[b - (1 << j) + 1,j];
}
static
int
findDistance(
int
n1,
int
n2) {
int
prevn1 = n1, prevn2 = n2;
n1 = H[n1];
n2 = H[n2];
if
(n2 < n1)
{
int
temp = n1;
n1 = n2;
n2 = temp;
}
int
lca = LCA(n1, n2);
lca = Euler[lca];
return
level[prevn1] + level[prevn2] - 2 * level[lca];
}
static
void
preProcessing(Node root,
int
N)
{
eulerTree(root);
FindLevels(root);
preprocessEuler(2 * N - 1);
preprocessLCA(2 * N - 1);
}
public
static
void
Main(String[] args)
{
int
N = 8;
Node root =
new
Node(1);
root.left =
new
Node(2);
root.right =
new
Node(3);
root.left.left =
new
Node(4);
root.left.right =
new
Node(5);
root.right.left =
new
Node(6);
root.right.right =
new
Node(7);
root.right.left.right =
new
Node(8);
preProcessing(root, N);
Console.WriteLine(
"Dist(4, 5) = "
+ findDistance(4, 5));
Console.WriteLine(
"Dist(4, 6) = "
+ findDistance(4, 6));
Console.WriteLine(
"Dist(3, 4) = "
+ findDistance(3, 4));
Console.WriteLine(
"Dist(2, 4) = "
+ findDistance(2, 4));
Console.WriteLine(
"Dist(8, 5) = "
+ findDistance(8, 5));
}
}