This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define int long long
#define pb push_back
#define s second
#define f first
#define pf push_front
#define inf 100000000000000000
#define bitebi __builtin_popcountll
#define FOR( i , n ) for( int i = 0 ; i < n ; i ++ )
#define YES cout <<"YES\n"
#define NO cout << "NO\n"
#define debug cout << "Here Fine" << endl ;
#define pr pair < int , int >
#define fbo find_by_order // returns iterator
#define ook order_of_key // returns strictly less numbers than key
using namespace std ;
//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx,avx2,fma")
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
const double Pi=acos(-1.0);
const double EPS=1E-8;
const int mod =  1000000007 ;
const int mod1 = 998244353 ;
const int N = 2e5 + 10 ;
mt19937 R(time(0));
map < int , int > ma , ma1 ;
int node[ 4 * N ] , w[ N ] , inv[ N ] , ap[ N ] ;
void build( int v , int vl , int vr ){
	 if( vl == vr ){
	 	node[ v ] = ap[ vl ] ;
	 	return ;
	 }
	 int vm = ( vl + vr ) / 2 ;
	 build( v + v , vl , vm ) ;
	 build( v + v + 1 , vm + 1 , vr ) ;
	 node[ v ] = max( node[ v + v ] , node[ v + v + 1 ] ) ;
	 return ;
}
void update( int v , int vl , int vr , int pos ){
	 if( vl == vr ){
	 	node[ v ] = - 1 ;
	 	return ; 
	 }
	 int vm = ( vl + vr ) / 2 ;
	 if( vm >= pos ) update( v + v , vl , vm , pos ) ;
	 else update( v + v + 1 , vm + 1 , vr , pos ) ;
	 node[ v ] = max( node[ v + v ] , node[ v + v + 1 ] ) ; 
	 return ;
}
int get( int v , int vl , int vr , int l , int r ){
	if( l > r ) return -1 ;
	if( vl == l && vr == r ) return node[ v ] ;
	int vm = ( vl + vr ) / 2 ;
	int a = get( v + v , vl , vm , l , min( r , vm ) ) ;
	int b = get( v + v + 1 , vm + 1 , vr , max( vm + 1 , l ) , r ) ;
	return max( a , b ) ;
}
vector < int > v[ N ] ;
int h[ N ] , tin[ N ] , tout[ N ] , timer = 1 ; 
int pp[ N ][ 20 ] , xx[ 20 ] , n ; 
void dfs( int node , int parent , int hh ){
	 ap[ timer ] = w[ node ] ;
	 tin[ node ] = timer ; 
	 h[ node ] = hh ;
	 timer ++ ; 
	 pp[ node ][ 0 ] = parent ;
	 for( int j = 1 ; j < 20 ; j ++ ){
	 	if( hh - xx[ j ] < 0 ) pp[ node ][ j ] = -1 ;
	 	else pp[ node ][ j ] = pp[ pp[ node ][ j - 1 ] ][ j - 1 ] ; 
	 }
	 for( auto x : v[ node ] ){
	 	if( x == parent ) continue ;
	 	dfs( x , node , hh + 1 ) ; 
	 }
	 tout[ node ] = timer - 1 ; 
}
bool is_lca( int a , int b ){
	if( a == -1 ) return true ; 
	if( a == b ) return true ;
	if( tin[ a ] <= tin[ b ] && tout[ a ] >= tout[ b ] ) return true ;
	return false ; 
}
int find_lca( int a , int b ){
	if( is_lca( a , b ) == true ) return a ;
	if( is_lca( b , a ) == true ) return b ;
	for( int j = 19 ; j >= 0 ; j -- ){
		if( is_lca( pp[ a ][ j ] , b ) == false ) a = pp[ a ][ j ] ; 
	}
	return pp[ a ][ 0 ] ; 
}
int dist( int a , int b ){
	if( a == -1 || b == -1 ) return 0 ;
	int c = find_lca( a , b ) ;
	int ans = abs( h[ c ] - h[ a ] ) + abs( h[ c ] - h[ b ] ) ;
	return ans ; 
}
int been[ N ] ; 
int sol( int st , int frm , int papi ){
//	cout << st << " " << frm << " " << papi << " tur " ; 
	int alr = dist( st , frm ) ;
//	cout << alr << endl ; 
	been[ st ] = 1 ;
	update( 1 , 1 , n , tin[ st ] ) ; 
	int ans = alr ; 
	for( auto x : v[ st ] ){
		if( h[ x ] < h[ st ] ) continue ; 
		if( been[ x ] == 1 ) continue ; 
		int mx = get( 1 , 1 , n , tin[ x ] , tout[ x ] ) ; 
		if( mx == -1 ) continue ; 
		mx = inv[ mx ] ;
		ans = max( ans , sol( mx , st , x ) + alr ) ; 
	}
   if( papi != -1 ){
	int x = papi ; 
	int mx = get( 1 , 1 , n , tin[ x ] , tout[ x ] ) ;
	if( mx != -1 ){
        mx = inv[ mx ] ; 
    	ans = max( ans , sol( mx , st , x ) + alr ) ;
    }
   }
	return ans ; 
}
void solve(){
     cin >> n ;
     FOR( i , n ){
     	cin >> w[ i + 1 ] ;
     	inv[ w[ i + 1 ] ] = i + 1 ; 
	 }
     FOR( i , n - 1 ){
     	int x , y ; cin >> x >> y ;
     	v[ x ].pb( y ) ; v[ y ].pb( x ) ; 
	 }
     dfs( inv[ n ] , -1 , 0 ) ; 
     build( 1 , 1 , n ) ; 
     int ans = sol( inv[ n ] , -1 , -1 ) ; 
     cout << ans ; 
}
signed main() {
   ios_base::sync_with_stdio(0),cin.tie(NULL),cout.tie(NULL);
   xx[ 0 ] = 1 ; 
   for( int j = 1 ; j < 20 ; j ++ ) xx[ j ] = xx[ j - 1 ] * 2 ; 
   int t = 1 ; // cin >> t ;
   while( t -- ){
   	 solve() ;
   }
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |