IOICJ 108 Where is He! ( Tree, Timestamp )
Problem Description:
You are given a tree with N nodes. There are Q queries, with u, v, w, where you want to know the node x such that x is a node in the simple path between u and v, where it is also the nearest to w.
Constraints:
1≤T≤50
2≤N,Q≤1e5
1≤a,b,u,v,w≤N
Sample Input:
1
6 2
1 2
2 4
4 5
2 3
3 6
1 6 5
4 5 1
Sample Output:
2
4
Solution:
If w is out of subtree of root lca( u, v ), then x is lca( u, v ).
Otherwise x is either lca( w, u ) or lca( w, v ).
#include <bits/stdc++.h> using namespace std; typedef vector< int > vi; typedef vector< vi > vvi; int T; const int MAXN = ( int ) 1e5; int N, Q; vvi G; void init(){ cin >> N >> Q; G = vvi( N ); for( int i = 0; i < N - 1; ++i ){ int u, v; cin >> u >> v; --u, --v; G[ u ].emplace_back( v ); G[ v ].emplace_back( u ); } } int TS; int tin[ MAXN ], tout[ MAXN ]; void ts_dfs( int u, int fa ){ tin[ u ] = ++TS; for( int v : G[ u ] ){ if( v == fa ) continue; ts_dfs( v, u ); } tout[ u ] = TS; } int dpt[ MAXN ], par[ 20 ][ MAXN ]; void lca_dfs( int u, int fa, int d ){ dpt[ u ] = d; par[ 0 ][ u ] = fa; for( int v : G[ u ] ){ if( v == fa ) continue; lca_dfs( v, u, d + 1 ); } } int lca( int u, int v ){ if( not ( dpt[ u ] >= dpt[ v ] ) ) swap( u, v ); int diff = dpt[ u ] - dpt[ v ]; for( int i = 20 - 1; diff; --i ){ if( diff >= 1 << i ){ diff -= 1 << i; u = par[ i ][ u ]; } } if( u == v ) return u; for( int i = 20 - 1; i >= 0; --i ){ if( par[ i ][ u ] != par[ i ][ v ] ){ u = par[ i ][ u ]; v = par[ i ][ v ]; } } return par[ 0 ][ u ]; } void solve(){ TS = 0; ts_dfs( 0, -1 ); for( int i = 0; i < 20; ++i ){ for( int j = 0; j < N; ++j ){ par[ i ][ j ] = -1; } } lca_dfs( 0, -1, 0 ); for( int i = 0; i + 1 < 20; ++i ){ for( int j = 0; j < N; ++j ){ int m = par[ i ][ j ]; if( m == -1 ) continue; par[ i + 1 ][ j ] = par[ i ][ m ]; } } for( int qi = 0; qi < Q; ++qi ){ int u, v, w; cin >> u >> v >> w; --u, --v, --w; int f = lca( u, v ); if( tin[ w ] < tin[ f ] or tout[ f ] < tin[ w ] ){ cout << f + 1 << endl; // out of subtree } else{ int a = lca( w, u ); int b = lca( w, v ); if( dpt[ w ] - dpt[ a ] < dpt[ w ] - dpt[ b ] ){ cout << a + 1 << endl; } else{ cout << b + 1 << endl; } } } } signed main(){ ios::sync_with_stdio( 0 ); cin >> T; for( int ti = 0; ti < T; ++ti ){ init(); solve(); } return 0; }