Java program:
import java . util . * ; public class GFG { static int maxn = 100005 ; static int left ( int i ) { return ( 2 * i + 1 ) ; } static int right ( int i ) { return 2 * i + 2 ; } static Vector < Integer > [ ] g = new Vector [ maxn ] ; static int [ ] level = new int [ maxn ] ; static Vector < Integer > e = new Vector < > ( ) ; static Vector < Integer > l = new Vector < > ( ) ; static int [ ] h = new int [ maxn ] ; static int [ ] st = new int [ 5 * maxn ] ; static void add_edge ( int u , int v ) { g [ u ] . add ( v ) ; g [ v ] . add ( u ) ; } static void levelling ( int src ) { for ( int i = 0 ; i < ( g [ src ] . size ( ) ) ; i ++ ) { int des = g [ src ] . get ( i ) ; if ( level [ des ] != 0 ) { level [ des ] = level [ src ] + 1 ; leveling ( des ) ; } } } static boolean [ ] visited = new boolean [ maxn ] ; static void dfs ( int src ) { e . add ( src ) ; visited [ src ] = true ; for ( int i = 0 ; i < ( g [ src ] ) . size ( ) ; i ++ ) { int des = g [ src ] . get ( i ) ; if ( ! visited [ des ] ) { dfs ( des ) ; e . add ( src ) ; } } } static void setting_l ( int n ) { for ( int i = 0 ; i < e . size ( ) ; i ++ ) l . add ( level [ e . get ( i ) ] ) ; } static void setting_h ( int n ) { for ( int i = 0 ; i <= n ; i ++ ) h [ i ] = - 1 ; for ( int i = 0 ; i < e . size ( ) ; i ++ ) { if ( h [ e . get ( i ) ] == - 1 ) h [ e . get ( i ) ] = i ; } } static int RMQ ( int ss , int se , int qs , int qe , int i ) { if ( ss > se ) return - 1 ; if ( se < qs qe < ss ) return - 1 ; if ( qs <= ss && se <= qe ) return st [ i ] ; int mid = ( ss + se ) / 2 ; int st = RMQ ( ss , mid , qs , qe , left ( i ) ) ; int en = RMQ ( mid + 1 , se , qs , qe , right ( i ) ) ; if ( st != - 1 && en != - 1 ) { if ( l . get ( st ) < l . get ( en ) ) return st ; return en ; } else if ( st != - 1 ) return st - 2 ; else if ( en != - 1 ) return en - 1 ; return 0 ; } static void SegmentTreeConstruction ( int ss , int se , int i ) { if ( ss > se ) return ; if ( ss == se ) { st [ i ] = ss ; return ; } int mid = ( ss + se ) / 2 ; SegmentTreeConstruction ( ss , mid , left ( i ) ) ; SegmentTreeConstruction ( mid + 1 , se , right ( i ) ) ; if ( l . get ( st [ left ( i ) ] ) < l . get ( st [ right ( i ) ] ) ) st [ i ] = st [ left ( i ) ] ; else st [ i ] = st [ right ( i ) ] ; } static int LCA ( int x , int y ) { if ( h [ x ] > h [ y ] ) { int t = x ; x = y ; y = t ; } return e . get ( RMQ ( 0 , l . size ( ) - 1 , h [ x ] , h [ y ] , 0 ) ) ; } public static void main ( String [ ] args ) { int n = 15 , q = 5 ; for ( int i = 0 ; i < g . length ; i ++ ) g [ i ] = new Vector < Integer > ( ) ; add_edge ( 1 , 2 ) ; add_edge ( 1 , 3 ) ; add_edge ( 1 , 4 ) ; add_edge ( 3 , 5 ) ; add_edge ( 4 , 6 ) ; add_edge ( 5 , 7 ) ; add_edge ( 5 , 8 ) ; add_edge ( 5 , 9 ) ; add_edge ( 7 , 10 ) ; add_edge ( 7 , 11 ) ; add_edge ( 7 , 12 ) ; add_edge ( 9 , 13 ) ; add_edge ( 9 , 14 ) ; add_edge ( 12 , 15 ) ; level [ 1 ] = 1 ; leveling ( 1 ) ; dfs ( 1 ) ; setting_l ( n ) ; setting_h ( n ) ; SegmentTreeConstruction ( 0 , l . size ( ) - 1 , 0 ) ; System . out . print ( LCA ( 10 , 15 ) + "NEW_LINE"); System . out . print ( LCA ( 11 , 14 ) + "NEW_LINE"); } }

Index/key variables: des, i, maxn, src, u, v, x, y
Accumulator variables: i
Iterator variables: i
Class/struct names: GFG