#include <bits/stdc++.h>
using namespace std;
using ld = long double;
using ll = long long;
const int INF = 1e9, MOD = 1e9 + 7;
void solve();
signed main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int q = 1;
while (q--) {
solve();
}
}
vector<vector<int>> g;
vector<int> val;
vector<int> fl;
vector<vector<int>> up, mx;
vector<int> tin, tout;
int timer = 1;
void ups(int v, int p) {
up[v][0] = p;
mx[v][0] = max(val[v], val[p]);
tin[v] = timer++;
for (int i = 1; i < 20; i++) {
up[v][i] = up[up[v][i - 1]][i - 1];
mx[v][i] = max(mx[v][i - 1], mx[up[v][i - 1]][i - 1]);
}
for (auto u: g[v]) {
if (u != p) {
fl[u] = fl[v] + 1;
ups(u, v);
}
}
tout[v] = timer++;
}
bool ch(int a, int b) {
return tin[a] <= tin[b] && tout[a] >= tout[b];
}
int lc(int a, int b) {
if (ch(a, b)) return a;
if (ch(b, a)) return b;
for (int i = 19; i >= 0; i--) {
int v = up[a][i];
if (ch(v, b)) continue;
a = v;
}
return up[a][0];
}
int gt(int a, int ds) {
int ans = val[a];
for (int i = 19; i >= 0; i--) {
if (ds - (1 << i) >= 0) {
ans = max(ans, mx[a][i]);
ds -= (1 << i);
a = up[a][i];
}
}
return ans;
}
pair<int, int> clc(int a, int b) {
int lca = lc(a, b);
int dist = fl[a] + fl[b] - 2 * fl[lca];
int m = max(gt(a, fl[a] - fl[lca]), gt(b, fl[b] - fl[lca]));
return {dist, m};
}
vector<int> sz, par, used, lev;
vector<vector<int>> ds, num;
vector<vector<int>> l, r;
void get_sz(int v, int p) {
sz[v] = 1;
for (auto u: g[v]) {
if (u == p || used[u]) continue;
get_sz(u, v);
sz[v] += sz[u];
}
}
int Find_centroid(int v, int p, int aint) {
int next = -1;
for (auto u: g[v]) {
if (u == p || used[u]) continue;
if (sz[u] > aint / 2) next = u;
}
if (next == -1) return v;
return Find_centroid(next, v, aint);
}
struct sg {
vector<int> tree;
void change(int v, int vl, int vr, int pos, int x) {
if (vr - vl == 1) {
if (x == -INF) {
tree[v] = x;
} else {
tree[v] = max(tree[v], x);
}
return;
}
int m = (vl + vr) / 2;
if (pos < m) {
change(2 * v, vl, m, pos, x);
} else {
change(2 * v + 1, m, vr, pos, x);
}
tree[v] = max(tree[2 * v], tree[2 * v + 1]);
}
int get(int v, int vl, int vr, int lq, int rq) {
if (vl >= rq || vr <= lq) {
return -INF;
}
if (vl >= lq && vr <= rq) {
return tree[v];
}
int m = (vl + vr) / 2;
return max(get(2 * v, vl, m, lq, rq), get(2 * v + 1, m, vr, lq, rq));
}
};
vector<sg> cnt;
void calc(int v, int p, int f, int lv, int lf, int rf, int c, int &id) {
ds[lv][v] = f;
num[lv][v] = id++;
l[lv][v] = lf;
r[lv][v] = rf;
for (auto u: g[v]) {
if (u == p || used[u]) continue;
calc(u, v, f + 1, lv, lf, rf, c, id);
}
}
void build(int v, int p, int level) {
get_sz(v, -1);
v = Find_centroid(v, -1, sz[v]);
lev[v] = level;
par[v] = p;
used[v] = 1;
get_sz(v, -1);
int id = 1;
ds[level][v] = 0;
num[level][v] = 0;
cnt[v].tree.resize(4 * sz[v], -INF);
for (auto u: g[v]) {
if (used[u]) continue;
calc(u, -1, 1, level, id, id + sz[u] - 1, v, id);
}
for (auto u: g[v]) {
if (!used[u]) build(u, v, level + 1);
}
}
vector<int> p;
vector<vector<int>> del;
void upd(int c, int v, int x) {
if (c == -1) return;
if (!del[lev[c]][v]) {
cnt[c].change(1, 0, (int)cnt[c].tree.size() / 4, num[lev[c]][v], x + ds[lev[c]][v]);
}
upd(par[c], v, x);
}
void dfs(int v, int c) {
int lv = lev[c];
del[lv][v] = 1;
cnt[c].change(1, 0, (int)cnt[c].tree.size() / 4, num[lv][v], -INF);
for (auto u: g[v]) {
if (lev[u] < lev[c]) continue;
if (ds[lv][u] < ds[lv][v]) continue;
if (del[lv][u]) continue;
dfs(u, c);
}
}
void deleted(int c, int v) {
if (c == -1) return;
dfs(v, c);
deleted(par[c], v);
}
void get(int c, int v, int &ans) {
if (c == -1) return;
auto [d, m] = clc(c, v);
if (m > val[v]) {
get(par[c], v, ans);
return;
}
if (v == c) {
ans = max(ans, cnt[c].tree[1] + d);
get(par[c], v, ans);
return;
}
int len = (int)cnt[c].tree.size() / 4;
ans = max(ans, cnt[c].get(1, 0, len, 0, l[lev[c]][v]) + d);
ans = max(ans, cnt[c].get(1, 0, len, r[lev[c]][v] + 1, len) + d);
get(par[c], v, ans);
}
void solve() {
int n;
cin >> n;
p.resize(n), val.resize(n);
for (int i = 0; i < n; i++) {
cin >> val[i];
val[i]--;
p[val[i]] = i;
}
g.resize(n);
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
a--, b--;
g[a].push_back(b);
g[b].push_back(a);
}
up.resize(n, vector<int>(20));
mx.resize(n, vector<int>(20));
fl.resize(n);
tin.resize(n), tout.resize(n);
ups(0, 0);
sz.resize(n), par.resize(n, -1),
used.resize(n), lev.resize(n);
ds.resize(20, vector<int>(n));
num.resize(20, vector<int>(n, -1));
l.resize(20, vector<int>(n));
r.resize(20, vector<int>(n));
del.resize(20, vector<int>(n));
cnt.resize(n);
build(0, -1, 0);
vector<int> dp(n, -INF);
dp[n - 1] = 0;
for (auto v: g[p[n - 1]]) {
upd(v, v, 1);
}
deleted(p[n - 1], p[n - 1]);
for (int i = n - 2; i >= 0; i--) {
get(p[i], p[i], dp[i]);
for (auto v: g[p[i]]) {
upd(v, v, dp[i] + 1);
}
deleted(p[i], p[i]);
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, dp[i]);
}
cout << ans;
}