Array Binary Search Bit Manipulation Depth-First Search Dynamic Programming Tree Source Weekly Contest 454 Q4 Difficulty Hard Rating 2428
Description You are given an integer n and an undirected, weighted tree rooted at node 0 with n nodes numbered from 0 to n - 1. This is represented by a 2D array edges of length n - 1, where edges[i] = [ui , vi , wi ] indicates an edge from node ui to vi with weight wi .
The weighted median node is defined as the first node x on the path from ui to vi such that the sum of edge weights from ui to x is greater than or equal to half of the total path weight.
You are given a 2D integer array queries. For each queries[j] = [uj , vj ], determine the weighted median node along the path from uj to vj .
Return an array ans, where ans[j] is the node index of the weighted median for queries[j].
Example 1:
Input: n = 2, edges = [[0,1,7]], queries = [[1,0],[0,1]]
Output: [0,1]
Explanation:
Query Path Edge Weights Total Path Weight Half Explanation Answer [1, 0] 1 → 0 [7] 7 3.5 Sum from 1 → 0 = 7 >= 3.5, median is node 0. 0 [0, 1] 0 → 1 [7] 7 3.5 Sum from 0 → 1 = 7 >= 3.5, median is node 1. 1
Example 2:
Input: n = 3, edges = [[0,1,2],[2,0,4]], queries = [[0,1],[2,0],[1,2]]
Output: [1,0,2]
E xplanation:
Query Path Edge Weights Total Path Weight Half Explanation Answer [0, 1] 0 → 1 [2] 2 1 Sum from 0 → 1 = 2 >= 1, median is node 1. 1 [2, 0] 2 → 0 [4] 4 2 Sum from 2 → 0 = 4 >= 2, median is node 0. 0 [1, 2] 1 → 0 → 2 [2, 4] 6 3 Sum from 1 → 0 = 2 < 3. Sum from 1 → 2 = 2 + 4 = 6 >= 3, median is node 2. 2
Example 3:
Input: n = 5, edges = [[0,1,2],[0,2,5],[1,3,1],[2,4,3]], queries = [[3,4],[1,2]]
Output: [2,2]
Explanation:
Query Path Edge Weights Total Path Weight Half Explanation Answer [3, 4] 3 → 1 → 0 → 2 → 4 [1, 2, 5, 3] 11 5.5 Sum from 3 → 1 = 1 < 5.5. Sum from 3 → 0 = 1 + 2 = 3 < 5.5. Sum from 3 → 2 = 1 + 2 + 5 = 8 >= 5.5, median is node 2. 2 [1, 2] 1 → 0 → 2 [2, 5] 7 3.5 Sum from 1 → 0 = 2 < 3.5. Sum from 1 → 2 = 2 + 5 = 7 >= 3.5, median is node 2.
2
Constraints:
2 <= n <= 105 edges.length == n - 1 edges[i] == [ui , vi , wi ] 0 <= ui , vi < n 1 <= wi <= 109 1 <= queries.length <= 105 queries[j] == [uj , vj ] 0 <= uj , vj < n The input is generated such that edges represents a valid tree. Solutions Solution 1: LCA + Binary Lifting Thinking
The weighted median is the first vertex on \(u \to v\) whose prefix weight from \(u\) is at least half the path. \(n,q \le 10^5\) call for LCA and weighted prefixes.
After \(lca\) and the total \(W\) , binary-lift on \(u \to lca\) or \(lca \to v\) to the farthest node whose prefix is still \(< W/2\) , then take one more step.
Root the tree at node \(0\) . Use BFS to compute each node's depth \(\textit{depth}\) , parent \(p\) , and weighted distance \(\textit{dist}\) from the root, and build the binary lifting table \(f[i][j]\) as the \(2^j\) -th ancestor of \(i\) .
For a query \((u, v)\) : if \(u = v\) , the answer is \(u\) . Otherwise let \(x = \textit{lca}(u, v)\) and \(W = \textit{dist}[u] + \textit{dist}[v] - 2 \cdot \textit{dist}[x]\) . The weighted median is the first node on the path starting from \(u\) whose prefix weight is at least \(W / 2\) . We compare \(2 \cdot \textit{pref} \ge W\) to avoid floating-point arithmetic.
If \(2 \cdot (\textit{dist}[u] - \textit{dist}[x]) \ge W\) , the median lies on \(u \to x\) (including \(x\) ). Lift from \(u\) to the farthest ancestor \(k\) that still satisfies \(2 \cdot (\textit{dist}[u] - \textit{dist}[k]) < W\) , then take one parent step to \(p[k]\) . Otherwise the median lies on \(x \to v\) (excluding \(x\) ). Lift from \(v\) to the highest node whose depth is greater than \(x\) and \(2 \cdot (\textit{dist}[u] + \textit{dist}[k] - 2 \cdot \textit{dist}[x]) \ge W\) . The time complexity is \(O((n + q) \times \log n)\) , and the space complexity is \(O(n \times \log n)\) , where \(n\) is the number of nodes and \(q\) is the number of queries.
Python3 Java C++ Go TypeScript Rust C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 class Solution :
def findMedian (
self , n : int , edges : List [ List [ int ]], queries : List [ List [ int ]]
) -> List [ int ]:
m = n . bit_length ()
g = [[] for _ in range ( n )]
for u , v , w in edges :
g [ u ] . append (( v , w ))
g [ v ] . append (( u , w ))
f = [[ 0 ] * m for _ in range ( n )]
p = [ 0 ] * n
depth = [ 0 ] * n
dist = [ 0 ] * n
q = deque ([ 0 ])
while q :
i = q . popleft ()
f [ i ][ 0 ] = p [ i ]
for j in range ( 1 , m ):
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ]
for j , w in g [ i ]:
if j != p [ i ]:
p [ j ] = i
depth [ j ] = depth [ i ] + 1
dist [ j ] = dist [ i ] + w
q . append ( j )
ans = []
for u , v in queries :
if u == v :
ans . append ( u )
continue
x , y = u , v
if depth [ x ] < depth [ y ]:
x , y = y , x
for j in range ( m - 1 , - 1 , - 1 ):
if depth [ x ] - depth [ y ] >= ( 1 << j ):
x = f [ x ][ j ]
for j in range ( m - 1 , - 1 , - 1 ):
if f [ x ][ j ] != f [ y ][ j ]:
x , y = f [ x ][ j ], f [ y ][ j ]
if x != y :
x = p [ x ]
w = dist [ u ] + dist [ v ] - 2 * dist [ x ]
if 2 * ( dist [ u ] - dist [ x ]) >= w :
cur = u
for j in range ( m - 1 , - 1 , - 1 ):
k = f [ cur ][ j ]
if depth [ k ] >= depth [ x ] and 2 * ( dist [ u ] - dist [ k ]) < w :
cur = k
ans . append ( p [ cur ])
else :
cur = v
for j in range ( m - 1 , - 1 , - 1 ):
k = f [ cur ][ j ]
if (
depth [ k ] > depth [ x ]
and 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w
):
cur = k
ans . append ( cur )
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 class Solution {
public int [] findMedian ( int n , int [][] edges , int [][] queries ) {
int m = 32 - Integer . numberOfLeadingZeros ( n );
List < int []>[] g = new List [ n ] ;
Arrays . setAll ( g , i -> new ArrayList <> ());
for ( var e : edges ) {
int u = e [ 0 ] , v = e [ 1 ] , w = e [ 2 ] ;
g [ u ] . add ( new int [] { v , w });
g [ v ] . add ( new int [] { u , w });
}
int [][] f = new int [ n ][ m ] ;
int [] p = new int [ n ] ;
int [] depth = new int [ n ] ;
long [] dist = new long [ n ] ;
Deque < Integer > q = new ArrayDeque <> ();
q . offer ( 0 );
while ( ! q . isEmpty ()) {
int i = q . poll ();
f [ i ][ 0 ] = p [ i ] ;
for ( int j = 1 ; j < m ; ++ j ) {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ] ;
}
for ( var nxt : g [ i ] ) {
int j = nxt [ 0 ] , w = nxt [ 1 ] ;
if ( j != p [ i ] ) {
p [ j ] = i ;
depth [ j ] = depth [ i ] + 1 ;
dist [ j ] = dist [ i ] + w ;
q . offer ( j );
}
}
}
int [] ans = new int [ queries . length ] ;
for ( int i = 0 ; i < queries . length ; ++ i ) {
int u = queries [ i ][ 0 ] , v = queries [ i ][ 1 ] ;
if ( u == v ) {
ans [ i ] = u ;
continue ;
}
int x = u , y = v ;
if ( depth [ x ] < depth [ y ] ) {
int t = x ;
x = y ;
y = t ;
}
for ( int j = m - 1 ; j >= 0 ; -- j ) {
if ( depth [ x ] - depth [ y ] >= ( 1 << j )) {
x = f [ x ][ j ] ;
}
}
for ( int j = m - 1 ; j >= 0 ; -- j ) {
if ( f [ x ][ j ] != f [ y ][ j ] ) {
x = f [ x ][ j ] ;
y = f [ y ][ j ] ;
}
}
if ( x != y ) {
x = p [ x ] ;
}
long w = dist [ u ] + dist [ v ] - 2 * dist [ x ] ;
if ( 2 * ( dist [ u ] - dist [ x ] ) >= w ) {
int cur = u ;
for ( int j = m - 1 ; j >= 0 ; -- j ) {
int k = f [ cur ][ j ] ;
if ( depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ] ) < w ) {
cur = k ;
}
}
ans [ i ] = p [ cur ] ;
} else {
int cur = v ;
for ( int j = m - 1 ; j >= 0 ; -- j ) {
int k = f [ cur ][ j ] ;
if ( depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ] ) >= w ) {
cur = k ;
}
}
ans [ i ] = cur ;
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 class Solution {
public :
vector < int > findMedian ( int n , vector < vector < int >>& edges , vector < vector < int >>& queries ) {
int m = 32 - __builtin_clz ( n );
vector < vector < pair < int , int >>> g ( n );
for ( auto & e : edges ) {
int u = e [ 0 ], v = e [ 1 ], w = e [ 2 ];
g [ u ]. emplace_back ( v , w );
g [ v ]. emplace_back ( u , w );
}
vector < vector < int >> f ( n , vector < int > ( m ));
vector < int > p ( n ), depth ( n );
vector < long long > dist ( n );
queue < int > q ;
q . push ( 0 );
while ( ! q . empty ()) {
int i = q . front ();
q . pop ();
f [ i ][ 0 ] = p [ i ];
for ( int j = 1 ; j < m ; ++ j ) {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ];
}
for ( auto [ j , w ] : g [ i ]) {
if ( j != p [ i ]) {
p [ j ] = i ;
depth [ j ] = depth [ i ] + 1 ;
dist [ j ] = dist [ i ] + w ;
q . push ( j );
}
}
}
vector < int > ans ;
for ( auto & qq : queries ) {
int u = qq [ 0 ], v = qq [ 1 ];
if ( u == v ) {
ans . push_back ( u );
continue ;
}
int x = u , y = v ;
if ( depth [ x ] < depth [ y ]) {
swap ( x , y );
}
for ( int j = m - 1 ; ~ j ; -- j ) {
if ( depth [ x ] - depth [ y ] >= ( 1 << j )) {
x = f [ x ][ j ];
}
}
for ( int j = m - 1 ; ~ j ; -- j ) {
if ( f [ x ][ j ] != f [ y ][ j ]) {
x = f [ x ][ j ];
y = f [ y ][ j ];
}
}
if ( x != y ) {
x = p [ x ];
}
long long w = dist [ u ] + dist [ v ] - 2 * dist [ x ];
if ( 2 * ( dist [ u ] - dist [ x ]) >= w ) {
int cur = u ;
for ( int j = m - 1 ; ~ j ; -- j ) {
int k = f [ cur ][ j ];
if ( depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ]) < w ) {
cur = k ;
}
}
ans . push_back ( p [ cur ]);
} else {
int cur = v ;
for ( int j = m - 1 ; ~ j ; -- j ) {
int k = f [ cur ][ j ];
if ( depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w ) {
cur = k ;
}
}
ans . push_back ( cur );
}
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 func findMedian ( n int , edges [][] int , queries [][] int ) [] int {
m := bits . Len ( uint ( n ))
g := make ([][][ 2 ] int , n )
for _ , e := range edges {
u , v , w := e [ 0 ], e [ 1 ], e [ 2 ]
g [ u ] = append ( g [ u ], [ 2 ] int { v , w })
g [ v ] = append ( g [ v ], [ 2 ] int { u , w })
}
f := make ([][] int , n )
for i := range f {
f [ i ] = make ([] int , m )
}
p := make ([] int , n )
depth := make ([] int , n )
dist := make ([] int , n )
q := [] int { 0 }
for len ( q ) > 0 {
i := q [ 0 ]
q = q [ 1 :]
f [ i ][ 0 ] = p [ i ]
for j := 1 ; j < m ; j ++ {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ]
}
for _ , nxt := range g [ i ] {
j , w := nxt [ 0 ], nxt [ 1 ]
if j != p [ i ] {
p [ j ] = i
depth [ j ] = depth [ i ] + 1
dist [ j ] = dist [ i ] + w
q = append ( q , j )
}
}
}
ans := make ([] int , len ( queries ))
for i , qq := range queries {
u , v := qq [ 0 ], qq [ 1 ]
if u == v {
ans [ i ] = u
continue
}
x , y := u , v
if depth [ x ] < depth [ y ] {
x , y = y , x
}
for j := m - 1 ; j >= 0 ; j -- {
if depth [ x ] - depth [ y ] >= 1 << j {
x = f [ x ][ j ]
}
}
for j := m - 1 ; j >= 0 ; j -- {
if f [ x ][ j ] != f [ y ][ j ] {
x , y = f [ x ][ j ], f [ y ][ j ]
}
}
if x != y {
x = p [ x ]
}
w := dist [ u ] + dist [ v ] - 2 * dist [ x ]
if 2 * ( dist [ u ] - dist [ x ]) >= w {
cur := u
for j := m - 1 ; j >= 0 ; j -- {
k := f [ cur ][ j ]
if depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ]) < w {
cur = k
}
}
ans [ i ] = p [ cur ]
} else {
cur := v
for j := m - 1 ; j >= 0 ; j -- {
k := f [ cur ][ j ]
if depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w {
cur = k
}
}
ans [ i ] = cur
}
}
return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 function findMedian ( n : number , edges : number [][], queries : number [][]) : number [] {
const m = 32 - Math . clz32 ( n );
const g : number [][][] = Array . from ({ length : n }, () => []);
for ( const [ u , v , w ] of edges ) {
g [ u ]. push ([ v , w ]);
g [ v ]. push ([ u , w ]);
}
const f : number [][] = Array . from ({ length : n }, () => Array ( m ). fill ( 0 ));
const p : number [] = Array ( n ). fill ( 0 );
const depth : number [] = Array ( n ). fill ( 0 );
const dist : number [] = Array ( n ). fill ( 0 );
const q : number [] = [ 0 ];
for ( let qq = 0 ; qq < q . length ; ++ qq ) {
const i = q [ qq ];
f [ i ][ 0 ] = p [ i ];
for ( let j = 1 ; j < m ; ++ j ) {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ];
}
for ( const [ j , w ] of g [ i ]) {
if ( j !== p [ i ]) {
p [ j ] = i ;
depth [ j ] = depth [ i ] + 1 ;
dist [ j ] = dist [ i ] + w ;
q . push ( j );
}
}
}
const ans : number [] = [];
for ( const [ u , v ] of queries ) {
if ( u === v ) {
ans . push ( u );
continue ;
}
let x = u ,
y = v ;
if ( depth [ x ] < depth [ y ]) {
[ x , y ] = [ y , x ];
}
for ( let j = m - 1 ; j >= 0 ; -- j ) {
if ( depth [ x ] - depth [ y ] >= 1 << j ) {
x = f [ x ][ j ];
}
}
for ( let j = m - 1 ; j >= 0 ; -- j ) {
if ( f [ x ][ j ] !== f [ y ][ j ]) {
x = f [ x ][ j ];
y = f [ y ][ j ];
}
}
if ( x !== y ) {
x = p [ x ];
}
const w = dist [ u ] + dist [ v ] - 2 * dist [ x ];
if ( 2 * ( dist [ u ] - dist [ x ]) >= w ) {
let cur = u ;
for ( let j = m - 1 ; j >= 0 ; -- j ) {
const k = f [ cur ][ j ];
if ( depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ]) < w ) {
cur = k ;
}
}
ans . push ( p [ cur ]);
} else {
let cur = v ;
for ( let j = m - 1 ; j >= 0 ; -- j ) {
const k = f [ cur ][ j ];
if ( depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w ) {
cur = k ;
}
}
ans . push ( cur );
}
}
return ans ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 use std :: collections :: VecDeque ;
impl Solution {
pub fn find_median ( n : i32 , edges : Vec < Vec < i32 >> , queries : Vec < Vec < i32 >> ) -> Vec < i32 > {
let n = n as usize ;
let m = 32 - ( n as u32 ). leading_zeros () as usize ;
let mut g = vec! [ vec! []; n ];
for e in & edges {
let u = e [ 0 ] as usize ;
let v = e [ 1 ] as usize ;
let w = e [ 2 ] as i64 ;
g [ u ]. push (( v , w ));
g [ v ]. push (( u , w ));
}
let mut f = vec! [ vec! [ 0 ; m ]; n ];
let mut p = vec! [ 0 ; n ];
let mut depth = vec! [ 0 ; n ];
let mut dist = vec! [ 0 i64 ; n ];
let mut q = VecDeque :: new ();
q . push_back ( 0 );
while let Some ( i ) = q . pop_front () {
f [ i ][ 0 ] = p [ i ];
for j in 1 .. m {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ];
}
for & ( j , w ) in & g [ i ] {
if j != p [ i ] {
p [ j ] = i ;
depth [ j ] = depth [ i ] + 1 ;
dist [ j ] = dist [ i ] + w ;
q . push_back ( j );
}
}
}
let mut ans = Vec :: with_capacity ( queries . len ());
for qq in & queries {
let u = qq [ 0 ] as usize ;
let v = qq [ 1 ] as usize ;
if u == v {
ans . push ( u as i32 );
continue ;
}
let ( mut x , mut y ) = ( u , v );
if depth [ x ] < depth [ y ] {
std :: mem :: swap ( & mut x , & mut y );
}
for j in ( 0 .. m ). rev () {
if depth [ x ] - depth [ y ] >= ( 1 << j ) {
x = f [ x ][ j ];
}
}
for j in ( 0 .. m ). rev () {
if f [ x ][ j ] != f [ y ][ j ] {
x = f [ x ][ j ];
y = f [ y ][ j ];
}
}
if x != y {
x = p [ x ];
}
let w = dist [ u ] + dist [ v ] - 2 * dist [ x ];
if 2 * ( dist [ u ] - dist [ x ]) >= w {
let mut cur = u ;
for j in ( 0 .. m ). rev () {
let k = f [ cur ][ j ];
if depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ]) < w {
cur = k ;
}
}
ans . push ( p [ cur ] as i32 );
} else {
let mut cur = v ;
for j in ( 0 .. m ). rev () {
let k = f [ cur ][ j ];
if depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w {
cur = k ;
}
}
ans . push ( cur as i32 );
}
}
ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class Solution {
public int [] FindMedian ( int n , int [][] edges , int [][] queries ) {
int m = 32 - BitOperations . LeadingZeroCount (( uint ) n );
List < int [] > [] g = new List < int [] > [ n ];
for ( int i = 0 ; i < n ; ++ i ) {
g [ i ] = new List < int [] > ();
}
foreach ( var e in edges ) {
int u = e [ 0 ], v = e [ 1 ], w = e [ 2 ];
g [ u ]. Add ( new int [] { v , w });
g [ v ]. Add ( new int [] { u , w });
}
int [][] f = new int [ n ][];
for ( int i = 0 ; i < n ; ++ i ) {
f [ i ] = new int [ m ];
}
int [] p = new int [ n ];
int [] depth = new int [ n ];
long [] dist = new long [ n ];
Queue < int > q = new Queue < int > ();
q . Enqueue ( 0 );
while ( q . Count > 0 ) {
int i = q . Dequeue ();
f [ i ][ 0 ] = p [ i ];
for ( int j = 1 ; j < m ; ++ j ) {
f [ i ][ j ] = f [ f [ i ][ j - 1 ]][ j - 1 ];
}
foreach ( var nxt in g [ i ]) {
int j = nxt [ 0 ], w = nxt [ 1 ];
if ( j != p [ i ]) {
p [ j ] = i ;
depth [ j ] = depth [ i ] + 1 ;
dist [ j ] = dist [ i ] + w ;
q . Enqueue ( j );
}
}
}
int [] ans = new int [ queries . Length ];
for ( int i = 0 ; i < queries . Length ; ++ i ) {
int u = queries [ i ][ 0 ], v = queries [ i ][ 1 ];
if ( u == v ) {
ans [ i ] = u ;
continue ;
}
int x = u , y = v ;
if ( depth [ x ] < depth [ y ]) {
int t = x ;
x = y ;
y = t ;
}
for ( int j = m - 1 ; j >= 0 ; -- j ) {
if ( depth [ x ] - depth [ y ] >= ( 1 << j )) {
x = f [ x ][ j ];
}
}
for ( int j = m - 1 ; j >= 0 ; -- j ) {
if ( f [ x ][ j ] != f [ y ][ j ]) {
x = f [ x ][ j ];
y = f [ y ][ j ];
}
}
if ( x != y ) {
x = p [ x ];
}
long w = dist [ u ] + dist [ v ] - 2 * dist [ x ];
if ( 2 * ( dist [ u ] - dist [ x ]) >= w ) {
int cur = u ;
for ( int j = m - 1 ; j >= 0 ; -- j ) {
int k = f [ cur ][ j ];
if ( depth [ k ] >= depth [ x ] && 2 * ( dist [ u ] - dist [ k ]) < w ) {
cur = k ;
}
}
ans [ i ] = p [ cur ];
} else {
int cur = v ;
for ( int j = m - 1 ; j >= 0 ; -- j ) {
int k = f [ cur ][ j ];
if ( depth [ k ] > depth [ x ] && 2 * ( dist [ u ] + dist [ k ] - 2 * dist [ x ]) >= w ) {
cur = k ;
}
}
ans [ i ] = cur ;
}
}
return ans ;
}
}
GitHub