#include <cstddef>
#include <utility>

template <class T, template <class> class StaticAllocator> class my_shared {
  using size_t = std::size_t;
  class node_type {
  public:
    T value;
    size_t count;

    template <class... Args>
    node_type(Args &&... args) : value(std::forward<Args>(args)...), count(1) {}
  };
  using allocator_type = StaticAllocator<node_type>;

  node_type *ptr;

  void sub_reset() noexcept {
    if (ptr && --ptr->count == 0) {
      allocator_type::destroy(ptr);
      allocator_type::deallocate(ptr);
    }
  }

public:
  constexpr my_shared() noexcept : ptr(nullptr) {}
  my_shared(const my_shared &r) noexcept : ptr(r.ptr) {
    if (ptr)
      ++ptr->count;
  }
  my_shared(my_shared &&r) noexcept : ptr(r.ptr) { r.ptr = nullptr; }
  constexpr my_shared(std::nullptr_t) noexcept : ptr() {}
  ~my_shared() noexcept { sub_reset(); }
  my_shared &operator=(const my_shared &r) noexcept {
    sub_reset();
    ptr = r.ptr;
    if (ptr)
      ++ptr->count;
    return *this;
  }
  my_shared &operator=(my_shared &&r) noexcept {
    sub_reset();
    ptr = r.ptr;
    r.ptr = nullptr;
    return *this;
  }
  void reset() noexcept {
    sub_reset();
    ptr = nullptr;
  }
  void swap(my_shared &r) noexcept { std::swap(ptr, r.ptr); }
  T *get() const noexcept { return &ptr->value; }
  T &operator*() const noexcept { return ptr->value; }
  T *operator->() const noexcept { return get(); }
  explicit operator bool() const noexcept { return ptr; }

  template <class... Args> static my_shared make(Args &&... args) {
    my_shared ret;
    ret.ptr = allocator_type::allocate();
    allocator_type::construct(ret.ptr, std::forward<Args>(args)...);
    return std::move(ret);
  }
};

#include <cstdlib>

template <class T> class my_allocator {
  static constexpr std::size_t AllocSize = 100000;
  union node_type {
    node_type *next;
    T value;
  };
  static node_type *pool;

public:
  static T *allocate() {
    if (!pool) {
      pool =
          reinterpret_cast<node_type *>(malloc(AllocSize * sizeof(node_type)));
      std::size_t i = AllocSize;
      pool[i - 1].next = nullptr;
      while (--i) {
        pool[i - 1].next = pool + i;
      }
    }
    node_type *ret = pool;
    pool = ret->next;
    return &ret->value;
  }
  static void deallocate(T *ptr) {
    node_type *temp = reinterpret_cast<node_type *>(ptr);
    temp->next = pool;
    pool = temp;
  }
  template <class... Args> static void construct(T *ptr, Args &&... args) {
    new (ptr) T(std::forward<Args>(args)...);
  }
  static void destroy(T *ptr) { ptr->~T(); }
};
template <class T>
typename my_allocator<T>::node_type *my_allocator<T>::pool = nullptr;

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <utility>

template <class T> class persistent_vector {
public:
  using value_type = T;
  using const_reference = const value_type &;
  using size_type = std::size_t;

protected:
  class node_t;
  using pointer = my_shared<const node_t, my_allocator>;
  using pair_ptr = std::pair<pointer, pointer>;
  using cptr_cref = const pointer &;
  using rank_type = std::uint_least8_t;
  class node_t {
  public:
    value_type value;
    size_type size;
    rank_type rank;
    pointer left, right;

    template <class... Args>
    explicit node_t(cptr_cref l, cptr_cref r, Args &&... args)
        : value(std::forward<Args>(args)...), size(nsize(l) + nsize(r) + 1),
          rank(std::max(nrank(l), nrank(r)) + 1), left(l), right(r) {}
  };
  static size_type nsize(cptr_cref c) { return c ? c->size : 0; }
  static rank_type nrank(cptr_cref c) { return c ? c->rank : 0; }
  static const_reference access(cptr_cref ptr, const size_type pos) {
    const size_type lsize = nsize(ptr->left);
    if (lsize == pos)
      return ptr->value;
    return lsize < pos ? access(ptr->right, pos - lsize - 1)
                       : access(ptr->left, pos);
  }
  static const_reference front(cptr_cref ptr) {
    return ptr->left ? front(ptr->left) : ptr->value;
  }
  static const_reference back(cptr_cref ptr) {
    return ptr->right ? back(ptr->right) : ptr->value;
  }

  static pointer make_l(const value_type &value, cptr_cref l, cptr_cref r) {
    if (nrank(l) != nrank(r) + 2)
      return pointer::make(l, r, value);
    if (nrank(l->left) + 1 == nrank(l->right)) {
      return pointer::make(pointer::make(l->left, l->right->left, l->value),
                           pointer::make(l->right->right, r, value),
                           l->right->value);
    } else {
      return pointer::make(l->left, pointer::make(l->right, r, value),
                           l->value);
    }
  }
  static pointer make_r(const value_type &value, cptr_cref l, cptr_cref r) {
    if (nrank(l) + 2 != nrank(r))
      return pointer::make(l, r, value);
    if (nrank(r->left) == nrank(r->right) + 1) {
      return pointer::make(pointer::make(l, r->left->left, value),
                           pointer::make(r->left->right, r->right, r->value),
                           r->left->value);
    } else {
      return pointer::make(pointer::make(l, r->left, value), r->right,
                           r->value);
    }
  }
  static pointer insert_back(cptr_cref ptr, cptr_cref elem) {
    return ptr ? make_r(ptr->value, ptr->left, insert_back(ptr->right, elem))
               : elem;
  }
  static pointer erase_back(cptr_cref ptr) {
    return ptr->right ? make_l(ptr->value, ptr->left, erase_back(ptr->right))
                      : ptr->left;
  }
  static pointer insert_front(cptr_cref ptr, cptr_cref elem) {
    return ptr ? make_l(ptr->value, insert_front(ptr->left, elem), ptr->right)
               : elem;
  }
  static pointer erase_front(cptr_cref ptr) {
    return ptr->left ? make_r(ptr->value, erase_front(ptr->left), ptr->right)
                     : ptr->right;
  }
  static pointer insert(cptr_cref ptr, const size_type pos, cptr_cref elem) {
    if (!ptr)
      return elem;
    if (nsize(ptr->left) < pos)
      return make_r(ptr->value, ptr->left,
                    insert(ptr->right, pos - nsize(ptr->left) - 1, elem));
    else
      return make_l(ptr->value, insert(ptr->left, pos, elem), ptr->right);
  }
  static pointer erase(cptr_cref ptr, const size_type pos) {
    if (nsize(ptr->left) < pos)
      return make_l(ptr->value, ptr->left,
                    erase(ptr->right, pos - nsize(ptr->left) - 1));
    else if (nsize(ptr->left) > pos)
      return make_r(ptr->value, erase(ptr->left, pos), ptr->right);
    else if (ptr->right)
      return make_l(front(ptr->right), ptr->left, erase_front(ptr->right));
    else
      return ptr->left;
  }
  static pointer merge_l(cptr_cref ptr, cptr_cref child,
                         const value_type &joint) {
    if (nrank(child) + 1 < nrank(ptr))
      return make_l(ptr->value, merge_l(ptr->left, child, joint), ptr->right);
    else
      return pointer::make(child, ptr, joint);
  }
  static pointer merge_r(cptr_cref ptr, cptr_cref child,
                         const value_type &joint) {
    if (nrank(child) + 1 < nrank(ptr))
      return make_r(ptr->value, ptr->left, merge_r(ptr->right, child, joint));
    else
      return pointer::make(ptr, child, joint);
  }
  static pointer merge(cptr_cref l, cptr_cref r, const value_type &joint) {
    return nrank(l) < nrank(r) ? merge_l(r, l, joint) : merge_r(l, r, joint);
  }
  static pair_ptr split(cptr_cref ptr, const size_type pos) {
    if (!pos)
      return pair_ptr(pointer(), ptr);
    if (nsize(ptr->left) < pos) {
      pair_ptr temp = split(ptr->right, pos - nsize(ptr->left) - 1);
      return pair_ptr(merge(ptr->left, temp.first, ptr->value), temp.second);
    } else {
      pair_ptr temp = split(ptr->left, pos);
      return pair_ptr(temp.first, merge(temp.second, ptr->right, ptr->value));
    }
  }

  pointer root;

  explicit persistent_vector(cptr_cref r) : root(r) {}

public:
  persistent_vector() : root() {}

  bool empty() const noexcept { return !root; }
  size_type size() const noexcept { return nsize(root); }

  const_reference operator[](const size_type i) const {
    assert(i < size());
    return access(root, i);
  }
  const_reference at(const size_type i) const {
    if (i < size())
      return access(root, i);
    else
      throw std::out_of_range("out of range");
  }
  const_reference front() const {
    assert(!empty());
    return front(root);
  }
  const_reference back() const {
    assert(!empty());
    return back(root);
  }

  persistent_vector insert(const size_type position,
                           const value_type &value) const {
    assert(position <= size());
    return persistent_vector(
        insert(root, position, pointer::make(pointer(), pointer(), value)));
  }
  template <class... Args>
  persistent_vector emplace(const size_type position, Args &&... args) const {
    assert(position <= size());
    return persistent_vector(insert(
        root, position,
        pointer::make(pointer(), pointer(), std::forward<Args>(args)...)));
  }
  persistent_vector erase(const size_type position) {
    assert(position < size());
    return persistent_vector(erase(root, position));
  }
  persistent_vector push_back(const value_type &value) const {
    return persistent_vector(
        insert_back(root, pointer::make(pointer(), pointer(), value)));
  }
  template <class... Args>
  persistent_vector emplace_back(Args &&... args) const {
    return persistent_vector(
        insert_back(root, pointer::make(pointer(), pointer(),
                                        std::forward<Args>(args)...)));
  }
  persistent_vector pop_back() const {
    assert(!empty());
    return persistent_vector(erase_back(root));
  }
  persistent_vector push_front(const value_type &value) const {
    return persistent_vector(
        insert_front(root, pointer::make(pointer(), pointer(), value)));
  }
  template <class... Args>
  persistent_vector emplace_front(Args &&... args) const {
    return persistent_vector(
        insert_front(root, pointer::make(pointer(), pointer(),
                                         std::forward<Args>(args)...)));
  }
  persistent_vector pop_front() const {
    assert(!empty());
    return persistent_vector(erase_front(root));
  }

  void clear() { root.reset(); }

  persistent_vector merge(const persistent_vector &other) const {
    return empty() ? other
                   : persistent_vector(
                         merge(erase_back(root), other.root, back(root)));
  }
  persistent_vector operator+(const persistent_vector &other) const {
    return merge(other);
  }
  std::pair<persistent_vector, persistent_vector>
  split(const size_type position) const {
    assert(position <= size());
    pair_ptr ret = split(root, position);
    return std::pair<persistent_vector, persistent_vector>(
        persistent_vector(ret.first), persistent_vector(ret.second));
  }
};

#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <numeric>


template <class T, class U>
inline bool chmin(T &lhs, const U &rhs) {
  if (lhs > rhs) {
    lhs = rhs;
    return true;
  }
  return false;
}

template <class T, class U>
inline bool chmax(T &lhs, const U &rhs) {
  if (lhs < rhs) {
    lhs = rhs;
    return true;
  }
  return false;
}

// [l, r) from l to r
struct range {
  struct itr {
    int i;
    constexpr itr(int i_): i(i_) { }
    constexpr void operator ++ () { ++i; }
    constexpr int operator * () const { return i; }
    constexpr bool operator != (itr x) const { return i != x.i; }
  };
  const itr l, r;
  constexpr range(int l_, int r_): l(l_), r(std::max(l_, r_)) { }
  constexpr itr begin() const { return l; }
  constexpr itr end() const { return r; }
};

// [l, r) from r to l
struct revrange {
  struct itr {
    int i;
    constexpr itr(int i_): i(i_) { }
    constexpr void operator ++ () { --i; }
    constexpr int operator * () const { return i; }
    constexpr bool operator != (itr x) const { return i != x.i; }
  };
  const itr l, r;
  constexpr revrange(int l_, int r_): l(l_ - 1), r(std::max(l_, r_) - 1) { }
  constexpr itr begin() const { return r; }
  constexpr itr end() const { return l; }
};

template <class T>
struct fix_point: private T {
  explicit constexpr fix_point(T &&func): T(std::forward<T>(func)) { }
  template <class... Args>
  constexpr decltype(auto) operator () (Args &&... args) const {
    return T::operator()(*this, std::forward<Args>(args)...);
  }
};

constexpr int inf = (1 << 30) - 1;

int main() {
  // int m, n;
  // std::string s;
  // std::cin >> m >> s >> n;
  // persistent_vector<char> pv;
  // for (const auto e : s)
  //   pv = pv.emplace_back(e);
  // while (n--) {
  //   int a, b, c;
  //   std::cin >> a >> b >> c;
  //   auto t = pv.split(b).first.split(a).second;
  //   auto u = pv.split(c);
  //   pv = u.first + t + u.second;
  //   if (int(pv.size()) > m)
  //     pv = pv.split(m).first;
  // }
  // for (int i = 0; i < int(pv.size()); ++i)
  //   std::cout << pv[i];
  // std::cout << std::endl;
  int N;
  std::cin >> N;
  std::vector<int> A(N);
  for (int &x: A) {
    std::cin >> x;
  }
  std::vector<std::vector<int>> graph(N);
  for (int i: range(0, N - 1)) {
    int a, b;
    std::cin >> a >> b;
    --a; --b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  persistent_vector<int> cur;
  cur = cur.emplace_back(0);
  for (int i: range(0, N)) {
    cur = cur.emplace_back(inf);
  }
  std::vector<int> ans(N);
  fix_point([&](auto dfs, int u, int p, persistent_vector<int> vec)-> void {
    int ok = N, ng = 0;
    while (ok - ng > 1) {
      int md = (ok + ng) >> 1;
      (vec.at(md) >= A[u] ? ok : ng) = md;
    }
    vec = vec.erase(ok);
    vec = vec.insert(ok, A[u]);
    for (int v: graph[u]) {
      if (v != p) {
        dfs(v, u, vec);
      }
    }
    ok = 0, ng = N + 1;
    while (ng - ok > 1) {
      int md = (ok + ng) >> 1;
      (vec.at(md) < inf ? ok : ng) = md;
    }
    ans[u] = ok;
  })(0, -1, cur);
  for (int x: ans) {
    std::cout << x << '\n';
  }
  return 0;
}


Measured memory_bytes: 238112