using
System;
using
System.Collections.Generic;
class
GFG
{
static
int
MAX = 100001;
public
class
Node
{
public
int
data;
public
Node left, right;
public
Node(
int
data)
{
this
.data = data;
this
.left =
this
.right =
null
;
}
}
class
Pair<T, V>
{
public
T first;
public
V second;
public
Pair() {
}
public
Pair(T first, V second)
{
this
.first = first;
this
.second = second;
}
}
static
int
[] level =
new
int
[MAX];
static
void
findLevels(Node root)
{
if
(root ==
null
)
return
;
List<Pair<Node,
int
>> q =
new
List<Pair<Node,
int
>>();
q.Add(
new
Pair<Node,
int
>(root, 0));
Pair<Node,
int
> p =
new
Pair<Node,
int
>();
while
(q.Count != 0)
{
p = q[0];
q.RemoveAt(0);
level[p.first.data] = p.second;
if
(p.first.left !=
null
)
q.Add(
new
Pair<Node,
int
>
(p.first.left, p.second + 1));
if
(p.first.right !=
null
)
q.Add(
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
Pair<
int
,
int
>[] seg =
new
Pair<
int
,
int
>[4 * MAX];
static
Pair<
int
,
int
> min(Pair<
int
,
int
> a,
Pair<
int
,
int
> b)
{
if
(a.first <= b.first)
return
a;
return
b;
}
static
Pair<
int
,
int
> buildSegTree(
int
low,
int
high,
int
pos)
{
if
(low == high)
{
seg[pos].first = L[low];
seg[pos].second = low;
return
seg[pos];
}
int
mid = low + (high - low) / 2;
buildSegTree(low, mid, 2 * pos);
buildSegTree(mid + 1, high, 2 * pos + 1);
seg[pos] = min(seg[2 * pos], seg[2 * pos + 1]);
return
seg[pos];
}
static
Pair<
int
,
int
> LCA(
int
qlow,
int
qhigh,
int
low,
int
high,
int
pos)
{
if
(qlow <= low && qhigh >= high)
return
seg[pos];
if
(qlow > high || qhigh < low)
return
new
Pair<
int
,
int
>(
int
.MaxValue, 0);
int
mid = low + (high - low) / 2;
return
min(LCA(qlow, qhigh, low, mid, 2 * pos),
LCA(qlow, qhigh, mid + 1,
high, 2 * pos + 1));
}
static
int
findDistance(
int
n1,
int
n2,
int
size)
{
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, 1, size, 1).second;
lca = Euler[lca];
return
level[prevn1] + level[prevn2] -
2 * level[lca];
}
static
void
preProcessing(Node root,
int
N)
{
for
(
int
i = 0; i < 4 * MAX; i++)
{
seg[i] =
new
Pair<
int
,
int
>();
}
eulerTree(root);
findLevels(root);
preprocessEuler(2 * N - 1);
buildSegTree(1, 2 * N - 1, 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, 2 * N - 1));
Console.WriteLine(
"Dist(4, 6) = "
+
findDistance(4, 6, 2 * N - 1));
Console.WriteLine(
"Dist(3, 4) = "
+
findDistance(3, 4, 2 * N - 1));
Console.WriteLine(
"Dist(2, 4) = "
+
findDistance(2, 4, 2 * N - 1));
Console.WriteLine(
"Dist(8, 5) = "
+
findDistance(8, 5, 2 * N - 1));
}
}