// C# program to find distance between
// two nodes for multiple queries
using System;
using System.Collections.Generic;
class GFG
{
static int MAX = 100001;
/* A tree node structure */
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;
}
}
// Array to store level of each node
static int[] level = new int[MAX];
// Utility Function to store level of all nodes
static void findLevels(Node root)
{
if (root == null)
return;
// queue to hold tree node with level
List<Pair<Node, int>> q =
new List<Pair<Node, int>>();
// let root node be at level 0
q.Add(new Pair<Node, int>(root, 0));
Pair<Node, int> p = new Pair<Node, int>();
// Do level Order Traversal of tree
while (q.Count != 0)
{
p = q[0];
q.RemoveAt(0);
// Node p.first is on level p.second
level[p.first.data] = p.second;
// If left child exits, put it in queue
// with current_level +1
if (p.first.left != null)
q.Add(new Pair<Node, int>
(p.first.left, p.second + 1));
// If right child exists, put it in queue
// with current_level +1
if (p.first.right != null)
q.Add(new Pair<Node, int>
(p.first.right, p.second + 1));
}
}
// Stores Euler Tour
static int[] Euler = new int[MAX];
// index in Euler array
static int idx = 0;
// Find Euler Tour
static void eulerTree(Node root)
{
// store current node's data
Euler[++idx] = root.data;
// If left node exists
if (root.left != null)
{
// traverse left subtree
eulerTree(root.left);
// store parent node's data
Euler[++idx] = root.data;
}
// If right node exists
if (root.right != null)
{
// traverse right subtree
eulerTree(root.right);
// store parent node's data
Euler[++idx] = root.data;
}
}
// checks for visited nodes
static int[] vis = new int[MAX];
// Stores level of Euler Tour
static int[] L = new int[MAX];
// Stores indices of first occurrence
// of nodes in Euler tour
static int[] H = new int[MAX];
// Preprocessing Euler Tour for finding LCA
static void preprocessEuler(int size)
{
for (int i = 1; i <= size; i++)
{
L[i] = level[Euler[i]];
// If node is not visited before
if (vis[Euler[i]] == 0)
{
// Add to first occurrence
H[Euler[i]] = i;
// Mark it visited
vis[Euler[i]] = 1;
}
}
}
// Stores values and positions
static Pair<int, int>[] seg = new
Pair<int, int>[4 * MAX];
// Utility function to find minimum of
// pair type values
static Pair<int, int> min(Pair<int, int> a,
Pair<int, int> b)
{
if (a.first <= b.first)
return a;
return b;
}
// Utility function to build segment tree
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];
}
// Utility function to find LCA
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));
}
// Function to return distance between
// two nodes n1 and n2
static int findDistance(int n1, int n2, int size)
{
// Maintain original Values
int prevn1 = n1, prevn2 = n2;
// Get First Occurrence of n1
n1 = H[n1];
// Get First Occurrence of n2
n2 = H[n2];
// Swap if low > high
if (n2 < n1)
{
int temp = n1;
n1 = n2;
n2 = temp;
}
// Get position of minimum value
int lca = LCA(n1, n2, 1, size, 1).second;
// Extract value out of Euler tour
lca = Euler[lca];
// return calculated distance
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>();
}
// Build Tree
eulerTree(root);
// Store Levels
findLevels(root);
// Find L and H array
preprocessEuler(2 * N - 1);
// Build segment Tree
buildSegTree(1, 2 * N - 1, 1);
}
// Driver Code
public static void Main(String[] args)
{
// Number of nodes
int N = 8;
/* Constructing tree given in the above figure */
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);
// Function to do all preprocessing
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));
}
}
// This code is contributed by Rajput-Ji