C# program:
using System ; public class GFG { static readonly int V = 5 ; static readonly int WHITE = 1 ; static readonly int BLACK = 2 ; public class Node { public int data ; public Node left , right ; } ; public class subset { public int parent ; public int rank ; public int ancestor ; public int child ; public int sibling ; public int color ; } ; public class Query { public int L , R ; public Query ( int L , int R ) { this . L = L ; this . R = R ; } } ; static Node newNode ( int data ) { Node node = new Node ( ) ; node . data = data ; node . left = node . right = null ; return ( node ) ; } static void makeSet ( subset [ ] subsets , int i ) { if ( i < 1 i > V ) return ; subsets [ i ] . color = WHITE ; subsets [ i ] . parent = i ; subsets [ i ] . rank = 0 ; return ; } static int findSet ( subset [ ] subsets , int i ) { if ( subsets [ i ] . parent != i ) subsets [ i ] . parent = findSet ( subsets , subsets [ i ] . parent ) ; return subsets [ i ] . parent ; } static void unionSet ( subset [ ] subsets , int x , int y ) { int xroot = findSet ( subsets , x ) ; int yroot = findSet ( subsets , y ) ; if ( subsets [ xroot ] . rank < subsets [ yroot ] . rank ) subsets [ xroot ] . parent = yroot ; else if ( subsets [ xroot ] . rank > subsets [ yroot ] . rank ) subsets [ yroot ] . parent = xroot ; else { subsets [ yroot ] . parent = xroot ; ( subsets [ xroot ] . rank ) ++ ; } } static void lcaWalk ( int u , Query [ ] q , int m , subset [ ] subsets ) { makeSet ( subsets , u ) ; subsets [ findSet ( subsets , u ) ] . ancestor = u ; int child = subsets [ u ] . child ; while ( child != 0 ) { lcaWalk ( child , q , m , subsets ) ; unionSet ( subsets , u , child ) ; subsets [ findSet ( subsets , u ) ] . ancestor = u ; child = subsets [ child ] . sibling ; } subsets [ u ] . color = BLACK ; for ( int i = 0 ; i < m ; i ++ ) { if ( q [ i ] . L == u ) { if ( subsets [ q [ i ] . R ] . color == BLACK ) { Console . WriteLine ( " LCA ( " + q [ i ] . L + " ▁ " + q [ i ] . R + " ) ▁ - > ▁ " + subsets [ findSet ( subsets , q [ i ] . R ) ] . ancestor ) ; } } else if ( q [ i ] . R == u ) { if ( subsets [ q [ i ] . L ] . color == BLACK ) { Console . WriteLine ( " LCA ( " + q [ i ] . L + " ▁ " + q [ i ] . R + " ) ▁ - > ▁ " + subsets [ findSet ( subsets , q [ i ] . L ) ] . ancestor ) ; } } } return ; } static void preprocess ( Node node , subset [ ] subsets ) { if ( node == null ) return ; preprocess ( node . left , subsets ) ; if ( node . left != null && node . right != null ) { subsets [ node . data ] . child = node . left . data ; subsets [ node . left . data ] . sibling = node . right . data ; } else if ( ( node . left != null && node . right == null ) || ( node . left == null && node . right != null ) ) { if ( node . left != null && node . right == null ) subsets [ node . data ] . child = node . left . data ; else subsets [ node . data ] . child = node . right . data ; } preprocess ( node . right , subsets ) ; } static void initialise ( subset [ ] subsets ) { for ( int i = 1 ; i < subsets . Length ; i ++ ) { subsets [ i ] = new subset ( ) ; subsets [ i ] . color = WHITE ; } return ; } static void printLCAs ( Node root , Query [ ] q , int m ) { subset [ ] subsets = new subset [ V + 1 ] ; initialise ( subsets ) ; preprocess ( root , subsets ) ; lcaWalk ( root . data , q , m , subsets ) ; } public static void Main ( String [ ] args ) { Node root = newNode ( 1 ) ; root . left = newNode ( 2 ) ; root . right = newNode ( 3 ) ; root . left . left = newNode ( 4 ) ; root . left . right = newNode ( 5 ) ; Query [ ] q = new Query [ 3 ] ; q [ 0 ] = new Query ( 5 , 4 ) ; q [ 1 ] = new Query ( 1 , 3 ) ; q [ 2 ] = new Query ( 2 , 3 ) ; int m = q . Length ; printLCAs ( root , q , m ) ; } }

Index/key variables: child, i, u, xroot, yroot
Accumulator variables: i
Iterator variables: i
Class/struct names: GFG, Node, Query, subset