Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices, whose i-th edge connects Vertex u_i and Vertex v_i.
Vertex i has an integer a_i written on it.
For every integer k from 1 through N, solve the following problem:

We will make a sequence by lining up the integers written on the vertices along the shortest path from Vertex 1 to Vertex k, in the order they appear. Find the length of the longest increasing subsequence of this sequence.

Here, the longest increasing subsequence of a sequence A of length L is the subsequence A_{i_1} , A_{i_2} , ... , A_{i_M} with the greatest possible value of M such that 1 \leq i_1 < i_2 < ... < i_M \leq L and A_{i_1} < A_{i_2} < ... < A_{i_M}.

Constraints

2 \leq N \leq 2 \times 10^5

1 \leq a_i \leq 10^9

1 \leq u_i , v_i \leq N

u_i \neq v_i

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 ... a_N
u_1 v_1
u_2 v_2
:
u_{N-1} v_{N-1}

Output

Print N lines. The k-th line, print the length of the longest increasing subsequence of the sequence obtained from the shortest path from Vertex 1 to Vertex k.

Sample Input 1

10
1 2 5 3 4 6 7 3 2 4
1 2
2 3
3 4
4 5
3 6
6 7
1 8
8 9
9 10

Sample Output 1

1
2
3
3
4
4
5
2
2
3

For example, the sequence A obtained from the shortest path from Vertex 1 to Vertex 5 is 1,2,5,3,4. Its longest increasing subsequence is A_1, A_2, A_4, A_5, with the length of 4.

Solution in Rust (1.42.0) (judge verdict: Accepted)

use proconio::{fastout, input};

use proconio::marker::Usize1;

#[fastout]
fn main() {
    input! {
        n: usize,
        a: [u64; n],
    }
    let mut g = vec![vec![]; n];
    for _ in 0..n - 1 {
        input! { u: Usize1, v: Usize1 }
        g[u].push(v);
        g[v].push(u);
    }
    let mut ans = vec![0; n];
    let mut lis = vec![a[0]];
    fn f(
        s: usize,
        p: usize,
        n: usize,
        a: &Vec<u64>,
        g: &Vec<Vec<usize>>,
        ans: &mut Vec<usize>,
        lis: &mut Vec<u64>,
    ) {
        ans[s] = lis.len();
        for &t in g[s].iter() {
            if t == p {
                continue;
            }
            let i = lis.lower_bound(&a[t]);
            if i < lis.len() {
                let prev = lis[i];
                lis[i] = a[t];
                f(t, s, n, a, g, ans, lis);
                lis[i] = prev;
            } else {
                lis.push(a[t]);
                f(t, s, n, a, g, ans, lis);
                lis.pop();
            }
        }
    };
    f(0, n, n, &a, &g, &mut ans, &mut lis);
    for &x in ans.iter() {
        println!("{}", x);
    }
}

use std::cmp::Ordering;
pub trait BinarySearch<T> {
    fn lower_bound(&self, x: &T) -> usize;
    fn upper_bound(&self, x: &T) -> usize;
    fn partition_point<F>(&self, f: F) -> usize
    where
        F: FnMut(&T) -> bool;
}
impl<T: Ord> BinarySearch<T> for [T] {
    fn lower_bound(&self, x: &T) -> usize {
        self.partition_point(|y| match y.cmp(x) {
            Ordering::Less => true,
            Ordering::Equal | Ordering::Greater => false,
        })
    }
    fn upper_bound(&self, x: &T) -> usize {
        self.partition_point(|y| match y.cmp(x) {
            Ordering::Less | Ordering::Equal => true,
            Ordering::Greater => false,
        })
    }
    fn partition_point<F>(&self, mut f: F) -> usize
    where
        F: FnMut(&T) -> bool,
    {
        let mut low = 0;
        let mut high = self.len();
        while low != high {
            let mid = (low + high) / 2;
            if f(&self[mid]) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        low
    }
}