#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define PI acos(-1)
#define vi vector<int>
#define pi pair<int, int>
#define pl pair<ll, ll>
template<class T> istream &operator>>(istream&is,vector<T>&v){for(auto &elemnt:v)is>>elemnt;return is;}
template<class T,class U> istream &operator>>(istream&is,pair<T,U>&p){is>>p.first>>p.second;return is;}
const int MOD = 1e9+ 7;
const int INF = numeric_limits<int>::max() - (int)1e8;
const ll INFLL = numeric_limits<ll>::max() - (ll)1e17;

template<typename T>
struct edge {
    pair<size_t, size_t> arrow;
    T cost;

    edge(size_t source, size_t to, T cost) : arrow(source, to), cost(cost) {}
    edge(size_t to, T cost) : arrow(-1, to), cost(cost) {}

    edge &operator=(const size_t &vertex) {
        arrow.second = vertex;
        return *this;
    }

    operator size_t() const { return arrow.second; }
};

template<typename T>
struct UnWeightedGraph {
    vector<vector<edge<T>>> data;
    bool is_directed_graph;

    explicit UnWeightedGraph(size_t size, bool is_directed_graph) : data(size), is_directed_graph(is_directed_graph) {}

    void add_edge(size_t source, size_t to) {
        data[source].emplace_back(to, 0);
        if (!is_directed_graph) data[to].emplace_back(source, 0);
    }

    vector<edge<T>> &operator[] (const size_t index) { return data[index]; }

    const size_t size() const { return data.size(); }
};

template<typename T>
struct WeightedGraph : UnWeightedGraph<T> {
    explicit WeightedGraph(size_t size, bool is_directed_graph) : UnWeightedGraph<T>(size, is_directed_graph) {}

    void add_edge(size_t source, size_t to, T cost) {
        UnWeightedGraph<T>::operator[](source).emplace_back(to, cost);
        if (!UnWeightedGraph<T>::is_directed_graph) UnWeightedGraph<T>::operator[](to).emplace_back(source, cost);
    }
};

template<typename T>
class EulerTour {
private:
    UnWeightedGraph<T> &graph;
    vector<size_t> euler_data, euler_in, euler_out;
    size_t data_size;

    void dfs(size_t now_vertex, size_t before_vertex, size_t &reference_count) {
        euler_in[now_vertex] = reference_count;
        euler_data[reference_count++] = now_vertex;
        for (auto next_vertex : graph[now_vertex]) {
            if (reference_count != 0 && next_vertex == before_vertex) continue;
            dfs(next_vertex, now_vertex, reference_count);
            euler_data[reference_count++] = now_vertex;
        }
        euler_out[now_vertex] = reference_count;
    }

public:
    explicit EulerTour(UnWeightedGraph<T> &graph) : graph(graph), euler_data(2 * graph.size()), euler_in(graph.size()), euler_out(graph.size()), data_size(0) {}

    void build(size_t start_vertex = 0) {
        size_t reference_count = 0;
        dfs(start_vertex, 0, reference_count);
        data_size = reference_count;
    }

    // [left, right) = [first, second)
    pair<int, int> index_of_vertex(const int vertex) { return {euler_in[vertex], euler_out[vertex]}; }

    int pre_oreder(const int vertex) {return euler_in[vertex]; }

    // When using it in a query, the closed-interval.
    int post_order(const int vertex) {return euler_out[vertex] - 1; }

    // read only
    const size_t &operator[] (const size_t index) const { return euler_data[index]; }

    size_t size() const noexcept { return data_size; }
};

template<typename T>
class UndoableLongestIncreaseingSubsequence {
private:
    struct operation_infomation {
        bool is_insert;
        T before, after;

        operation_infomation(bool is_insert, T before, T after) : is_insert(is_insert), before(before), after(after) {}
    };

    multiset<T> lis_data;
    list<operation_infomation> update_infomation;
    bool is_narrowly_sense;

public:
    explicit UndoableLongestIncreaseingSubsequence(bool is_narrowly_sense) : is_narrowly_sense(is_narrowly_sense) {}

    size_t update(T add) {
        typename multiset<T>::iterator iter;
        if (is_narrowly_sense) iter = lis_data.lower_bound(add);
        else iter = lis_data.upper_bound(add);
        if (iter == lis_data.end()) {
            lis_data.insert(add);
            update_infomation.emplace_back(true, add, add);   
        } else {
            update_infomation.emplace_back(false, *iter, add);
            lis_data.erase(iter);
            lis_data.insert(add);
        }
        return lis_data.size();
    }

    void undo() {
        if (lis_data.empty()) return;
        operation_infomation operation = update_infomation.back();
        auto iter = lis_data.lower_bound(operation.after);
        lis_data.erase(iter);
        if (!operation.is_insert) lis_data.insert(operation.before);
        update_infomation.erase(next(update_infomation.end(), -1));
    }
};

template<typename T>
class LongestIncreaseingSubsequenceTree {
private:

    UnWeightedGraph<T> tree;
    EulerTour<T> euler_tour;
    vector<T> vertex_number_data;
    vector<size_t> vertex_lis_size;
    UndoableLongestIncreaseingSubsequence<T> count_lis;

    void dfs() {
        for (size_t index = 0; index < euler_tour.size(); index++) {
            size_t now_vertex = euler_tour[index];
            size_t pre_order, post_order;
            tie(pre_order, post_order) = euler_tour.index_of_vertex(now_vertex);
            post_order--;
            if (pre_order == index) {
                vertex_lis_size[now_vertex] = count_lis.update(vertex_number_data[now_vertex]);
            }
            if (post_order == index) {
                count_lis.undo();
            }
        }
    }

public:
    explicit LongestIncreaseingSubsequenceTree(size_t vertex_size, bool is_narrowly_sense) 
        : tree(vertex_size, false), euler_tour(tree), vertex_number_data(vertex_size, 0), vertex_lis_size(vertex_size) , count_lis(is_narrowly_sense) {}
    
    void add_edge(size_t source, size_t to) { tree.add_edge(source, to); }

    void init_vertex(size_t vertex, T number) { vertex_number_data[vertex] = number; }

    void build(size_t start_vertex = 0) {
        euler_tour.build(start_vertex);
        dfs();
    }

    const size_t &operator[] (size_t vertex) { return vertex_lis_size[vertex]; }
};


int main() {
    int N;
    cin >> N;
    LongestIncreaseingSubsequenceTree<int> tree(N, true);
    for (int i = 0; i < N; i++) {
        int a;
        cin >> a;
        tree.init_vertex(i, a);
    }
    for (int i = 0; i < N - 1; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        tree.add_edge(u, v);
    }
    tree.build();
    for (int i = 0; i < N; i++) {
        cout << tree[i] << endl;
    }
}

Measured memory_bytes: 49188