#include <bits/stdc++.h>
using namespace std;
const int Maxn = 6010;
vector<int> V;
vector<int> G[Maxn];
int a[Maxn];
int dp[Maxn][2];
int n, ans;
int getid(int x) { return lower_bound(V.begin(), V.end(), x) - V.begin() + 1; }
struct Node *null;
struct Node {
  Node *ch[2];
  int r, v[2];
  int sz, u;
  int val[2];
  int cmp(int x) {
    if (a[u] == x) return -1;
    return a[u] < x;
  }
  void push_up() {
    if (this == null) return;
    sz = ch[0]->sz + ch[1]->sz + 1;
    v[0] = max(ch[0]->v[0], ch[1]->v[0]);
    v[0] = max(v[0], val[0]);
    v[1] = max(ch[0]->v[1], ch[1]->v[1]);
    v[1] = max(v[1], val[1]);
  }
};
Node *create(int u, int w1, int w2) {
  Node *ret = new Node();
  ret->r = rand();
  ret->ch[0] = ret->ch[1] = null;
  ret->u = u;
  ret->sz = 1;
  ret->val[0] = ret->v[0] = w1;
  ret->val[1] = ret->v[1] = w2;
  return ret;
}
int getmax(Node *rt, int w, int ty) {
  if (rt == null) return 0;
  int ret = 0;
  if (!ty) {
    if (a[rt->u] >= w)
      ret = max(ret, getmax(rt->ch[0], w, ty));
    else {
      ret = max(ret, rt->ch[0]->v[0]);
      ret = max(ret, rt->val[0]);
      ret = max(ret, getmax(rt->ch[1], w, ty));
    }
  } else {
    if (a[rt->u] <= w)
      ret = max(ret, getmax(rt->ch[1], w, ty));
    else {
      ret = max(ret, rt->ch[1]->v[1]);
      ret = max(ret, rt->val[1]);
      ret = max(ret, getmax(rt->ch[0], w, ty));
    }
  }
  return ret;
}
void rotate(Node *&o, int d) {
  Node *k = o->ch[d ^ 1];
  o->ch[d ^ 1] = k->ch[d];
  k->ch[d] = o;
  o->push_up();
  k->push_up();
  o = k;
}
void insert(Node *&o, int u, int w1, int w2) {
  if (o == null)
    o = create(u, w1, w2);
  else {
    int d = o->cmp(a[u]);
    insert(o->ch[d], u, w1, w2);
    if (o->ch[d]->r > o->r) rotate(o, d ^ 1);
    o->push_up();
  }
}
bool find(Node *o, int u, int w1, int w2) {
  if (o == null) return false;
  int d = o->cmp(a[u]);
  if (d == -1) {
    o->val[0] = max(o->val[0], w1);
    o->val[1] = max(o->val[1], w2);
    o->push_up();
    return true;
  }
  int t = find(o->ch[d], u, w1, w2);
  if (t) o->push_up();
  return t;
}
void merge(Node *rt, Node *&tar) {
  if (rt == null) return;
  if (!find(tar, rt->u, rt->val[0], rt->val[1]))
    insert(tar, rt->u, rt->val[0], rt->val[1]);
  if (rt->ch[0] != null) merge(rt->ch[0], tar);
  if (rt->ch[1] != null) merge(rt->ch[1], tar);
}
Node *dfs1(int u, int pre) {
  Node *ret = null;
  pair<int, int> tp[2][2];
  int p[2];
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) tp[i][j] = pair<int, int>(0, 0);
  for (int i = 0; i < G[u].size(); i++) {
    int v = G[u][i];
    if (v == pre) continue;
    Node *t = dfs1(v, u);
    p[0] = getmax(t, a[u], 0);
    p[1] = getmax(t, a[u], 1);
    if (p[0] > tp[0][0].first) {
      tp[0][1] = tp[0][0];
      tp[0][0] = pair<int, int>(p[0], i);
    } else if (p[0] > tp[0][1].first)
      tp[0][1] = pair<int, int>(p[0], i);
    if (p[1] > tp[1][0].first) {
      tp[1][1] = tp[1][0];
      tp[1][0] = pair<int, int>(p[1], i);
    } else if (p[1] > tp[1][1].first)
      tp[1][1] = pair<int, int>(p[1], i);
    if (ret->sz > t->sz)
      merge(t, ret);
    else {
      merge(ret, t);
      ret = t;
    }
  }
  dp[u][0] = tp[0][0].first + 1;
  dp[u][1] = tp[1][0].first + 1;
  if (tp[0][0].second != tp[1][0].second)
    ans = max(ans, tp[0][0].first + tp[1][0].first + 1);
  else {
    ans = max(ans, tp[0][0].first + tp[1][1].first + 1);
    ans = max(ans, tp[0][1].first + tp[1][0].first + 1);
  }
  if (!find(ret, u, dp[u][0], dp[u][1])) insert(ret, u, dp[u][0], dp[u][1]);
  return ret;
}
pair<int, int> tree[Maxn << 2];
void add(int tar, int w1, int w2, int l, int r, int x) {
  if (l == r) {
    tree[x].first = max(tree[x].first, w1);
    tree[x].second = max(tree[x].second, w2);
    return;
  }
  int mid = (l + r) >> 1;
  if (tar <= mid)
    add(tar, w1, w2, l, mid, x << 1);
  else
    add(tar, w1, w2, mid + 1, r, x << 1 | 1);
  tree[x].first = max(tree[x << 1].first, tree[x << 1 | 1].first);
  tree[x].second = max(tree[x << 1].second, tree[x << 1 | 1].second);
}
int query(int L, int R, int l, int r, int x, int ty) {
  if (L > R) return 0;
  if (L <= l && R >= r) {
    return ty ? tree[x].second : tree[x].first;
  }
  int mid = (l + r) >> 1;
  int ret = 0;
  if (L <= mid) ret = max(ret, query(L, R, l, mid, x << 1, ty));
  if (R > mid) ret = max(ret, query(L, R, mid + 1, r, x << 1 | 1, ty));
  return ret;
}
void dfs2(int u, int p) {
  ans = max(ans, dp[u][0] + query(a[u] + 1, n, 1, n, 1, 1));
  ans = max(ans, dp[u][1] + query(1, a[u] - 1, 1, n, 1, 0));
  for (int i = 0; i < G[u].size(); i++) {
    int v = G[u][i];
    if (v == p) continue;
    dfs2(v, u);
  }
  add(a[u], dp[u][0], dp[u][1], 1, n, 1);
}
int main() {
  null = new Node();
  null->ch[0] = null->ch[1] = null;
  null->sz = null->u = null->v[0] = null->v[1] = 0;
  null->val[0] = null->val[1] = 0;
  null->r = -1;
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", a + i);
    V.push_back(a[i]);
  }
  sort(V.begin(), V.end());
  V.erase(unique(V.begin(), V.end()), V.end());
  for (int i = 1; i <= n; i++) a[i] = getid(a[i]);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    G[u].push_back(v);
    G[v].push_back(u);
  }
  dfs1(1, 0);
  dfs2(1, 0);
  printf("%d\n", ans);
}
