#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define int long long
#define all(x) (x).begin(), (x).end()
typedef long double ld;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<bool> vb;
typedef vector<vector<int>> vvi;
typedef vector<vector<bool>> vvb;
typedef vector<vector<ll>> vvll;
typedef vector<string> vs;
typedef vector<vector<string>> vvs;
typedef vector<char> vc;
typedef vector<vector<char>> vvc;
typedef map<int, int> mii;
typedef unordered_map<int, int> umii;
const int mod = 1e9 + 7;
const int inf = INTMAX_MAX;
const bool tc = false;
int n; const int mxn = 2e5+5, LG = 20;
int p[mxn]; vi adj[mxn], adj2[mxn];
int dep[mxn], up[mxn][LG];
class DisjointSets {
private:
vector<int> parents;
vector<int> sizes;
vector<pii> mx;
public:
DisjointSets(int size) : parents(size), sizes(size, 1), mx(size) {
for (int i = 0; i < size; i++) { parents[i] = i; mx[i] = {p[i], i}; }
}
/** @return the "representative" node in x's component */
int find(int x) { return parents[x] == x ? x : (parents[x] = find(parents[x])); }
/** @return whether the merge changed connectivity */
bool unite(int x, int y) {
int x_root = find(x);
int y_root = find(y);
if (x_root == y_root) { return false; }
if (sizes[x_root] < sizes[y_root]) { swap(x_root, y_root); }
sizes[x_root] += sizes[y_root];
parents[y_root] = x_root;
pii z = max(mx[x_root], mx[y_root]);
mx[x_root] = mx[y_root] = z;
return true;
}
/** @return whether x and y are in the same connected component */
bool connected(int x, int y) { return find(x) == find(y); }
pii top(int u) { return mx[find(u)]; }
};
void dfsl(int u, int par) {
up[u][0] = par;
for (int j = 1; j < LG; j++) {
up[u][j] = up[up[u][j - 1]][j - 1];
}
for (int v : adj[u]) {
if (v == par) continue;
dep[v] = dep[u] + 1;
dfsl(v, u);
}
}
void build() {
dep[0] = 0;
dfsl(0, 0);
}
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
int d = dep[u] - dep[v];
for (int j = LG - 1; j >= 0; j--) {
if (d & (1 << j)) u = up[u][j];
}
if (u == v) return u;
for (int j = LG - 1; j >= 0; j--) {
if (up[u][j] != up[v][j]) {
u = up[u][j];
v = up[v][j];
}
}
return up[u][0];
}
int dist(int u, int v) {
int w = lca(u, v);
return dep[u] + dep[v] - 2 * dep[w];
}
int ans = -1;
void ansdfs(int node, int prev, int d) {
ans = max(ans, d);
for (auto &neighbour : adj2[node]) {
if (neighbour == prev) continue;
ansdfs(neighbour, node, d + dist(neighbour,node));
}
}
inline void solve() {
cin >> n; vector<pii> tp; int s = -1;
for (int i = 0; i < n; i++) {cin >> p[i]; tp.pb({p[i], i}); if (p[i] == n) s = i;}
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
u--; v--;
adj[u].pb(v);
adj[v].pb(u);
}
sort(all(tp)); build();
DisjointSets dsu(n);
for (auto &x : tp) {
int v = x.fi; int node = x.se;
for (auto &neighbour : adj[node]) {
if (p[neighbour]>p[node]) continue;
pii z = dsu.top(neighbour);
adj2[node].pb(z.se);
adj2[z.se].pb(node);
}
for (auto &neighbour : adj[node]) {
if (p[neighbour]<p[node]) dsu.unite(node, neighbour);
}
}
ans = -1; ansdfs(s, -1, 0);
cout << ans << '\n';
}
void setIO(string s) {
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
signed main() {
ios::sync_with_stdio(false);
cout.tie(0);
cin.tie(0);
//setIO();
int t = 1;
if (tc) {
cin >> t;
}
while (t--) {
solve();
}
}