#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

#ifndef INCLUDED_PERSISTENT_ARRAY_HPP
#define INCLUDED_PERSISTENT_ARRAY_HPP

#include <cstdint>
#include <cstring>
#include <vector>
#include <algorithm>

template<class T, std::uint_fast32_t K = 20>
class persistent_array {
	using u32 = std::uint_fast32_t;

public:
	using value_type = T;
	using size_type = u32;

private:
	struct node {
		T data;
		node* child[K];

		node() = default;
	};
	using node_ptr = node*;
	std::vector<node_ptr> root;

	void change(size_type idx, const T& val, node_ptr& t) {
		if(!t) t = new node();
		
		if(!idx) t->data = val;
		else change(idx / K, val, t->child[idx % K]);
	}
	node_ptr set(size_type idx, const T& val, const node_ptr& t) {
		node_ptr ret = new node();
		if(t) {
			std::memcpy(ret->child, t->child, sizeof(t->child));
			ret->data = t->data;
		}

		if(!idx) ret->data = val;
		else ret->child[idx % K] = set(idx / K, val, ret->child[idx % K]);
		return ret;
	}
	T get(size_type idx, const node_ptr& t) const {
		if(!t) return T{};
		if(idx == 0) return t->data;
		return get(idx / K, t->child[idx % K]);
	}

public:
	persistent_array(persistent_array&&) = default;
	persistent_array(const persistent_array &) = default;

	persistent_array(): root(1, nullptr) {}

	void change(size_type idx, const T& val, int time = -1) {
		if(time == -1) change(idx, val, root.back());
		else change(idx, val, root[time]);
	}
	size_type set(size_type idx, const T& val, int time = -1) {
		if(time == -1) root.push_back(set(idx, val, root.back()));
		else root.push_back(set(idx, val, root[time]));
		return root.size() - 1;
	}
	T get(size_type idx, int time = -1) const {
		if(time == -1) return get(idx, root.back());
		return get(idx, root[time]);
	}

	const T operator[](size_type k) const { return get(k); }
	bool empty() const { return (root.size() == 1 and root[0] == nullptr); }
	size_type now() const { return root.size() - 1; }
	void clear() { root.assign(1, nullptr); }
	void swap(const persistent_array& r) { root.swap(r.root); }
};

#endif

#define NDEBUG

int main() {
	int n; scanf("%d", &n);
	std::vector<int> h(n), a(n - 1), b(n - 1);
	std::vector<std::vector<int>> g(n);
	for(auto& v: h) scanf("%d", &v);
	for(int i = 0; i < n - 1; i++) {
		scanf("%d%d", &a[i], &b[i]);
		a[i]--; b[i]--;

		g[a[i]].push_back(i);
		g[b[i]].push_back(i);
	}


	std::stack<int> st;
	std::vector<int> ans(n);
	persistent_array<int> dp;
	for(int i = 0; i < n + 1; i++) dp.change(i, 1 << 30); dp.change(0, 0);

	auto f = [&](int x, int id) {
		int ok = 0, ng = n + 1;
		while(std::abs(ok - ng) > 1) {
			int mid = (ok + ng) >> 1;

			if(dp.get(mid, id) < x) ok = mid;
			else ng = mid;
		}
		return ok;
	};

	st.push(dp.now());
	auto solve = [&](auto&& solve, int v, int par) -> void {
		dp.set(f(h[v], st.top()) + 1, h[v], st.top());
		ans[v] = f(1 << 30, -1);

		#ifndef NDEBUG
		printf("%d: ", v + 1);
		for(int i = 0; i < n; i++) printf("%d ", dp[i]);
		printf("\n");
		#endif
		
		st.push(dp.now());
		for(int id: g[v]) {
			int to = a[id] ^ b[id] ^ v;
			if(to == par) continue;
			solve(solve, to, v);
		}
		st.pop();
	};
	solve(solve, 0, -1);

	for(auto v: ans) printf("%d\n", v);
	return 0;
}


Measured memory_bytes: 204596