#include<bits/stdc++.h>

#define ll long long
#define pp push_back
#define endl '\n'
#define all(x) x.begin(),x.end()
#define ld long double
#define PI acos(-1)
#define sin(a) sin((a)*PI/180)
#define cos(a) cos((a)*PI/180)
#define ones(x) __builtin_popcountll(x)
//#define int ll

using namespace std;

void Drakon() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef Clion
    freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#endif
}

unsigned long long inf = 1e10;
const double EPS = 1e-6;
const int MOD = 1000000007, N = 200005, LOG = 25;

ll mul(const ll &a, const ll &b) {
    return (a % MOD + MOD) * (b % MOD + MOD) % MOD;
}

ll add(const ll &a, const ll &b) {
    return (a + b + 2 * MOD) % MOD;
}

ll pw(ll x, ll y) {
    ll ret = 1;
    while (y > 0) {
        if (y % 2 == 0) {
            x = mul(x, x);
            y = y / 2;
        } else {
            ret = mul(ret, x);
            y = y - 1;
        }
    }
    return ret;
}

struct seg {
    int len = 0;

    seg() {

    }

    seg(int len) {
        this->len = len;
    }
};

struct segtree {

    vector<seg> values;
    int size = 1, n;

    void init(int nn) {
        n = nn;
        while (size < nn)size *= 2;
        values.resize(2 * size, seg());
    }

    seg mrg(seg &a, seg &b) {
        seg c;
        c.len = max(a.len, b.len);
        return c;
    }

    void update(int i, int v, int x, int lx, int rx) {

        if (lx == rx) {
            if(v == -1) values[x].len = 0;
            else values[x].len = max(values[x].len, v);
            return;
        }
        int mid = (lx + rx) / 2;
        if (i <= mid)
            update(i, v, 2 * x + 1, lx, mid);
        else
            update(i, v, 2 * x + 2, mid + 1, rx);
        values[x] = mrg(values[2 * x + 1], values[2 * x + 2]);
    }

    void update(int i, int v) {
        update(i, v, 0, 0, n - 1);
    }

    seg query(int l, int r, int x, int lx, int rx) {

        if (l > rx || lx > r) {
            return seg();
        }
        else if (lx >= l && rx <= r) {
            return values[x];
        }

        int mid = (lx + rx) / 2;
        seg s1 = query(l, r, 2 * x + 1, lx, mid);
        seg s2 = query(l, r, 2 * x + 2, mid + 1, rx);
        return mrg(s1, s2);
    }

    seg query(int l, int r) {
        return query(l, r, 0, 0, n - 1);
    }

};

vector<int> adj[N];
int n, sz[N], big[N];

void dfsSz(int u, int par) {
    sz[u] = 1;
    for (auto &v: adj[u]) {
        if (v == par)continue;
        dfsSz(v, u);
        sz[u] += sz[v];
        if (big[u] == -1 || sz[v] > sz[big[u]])
            big[u] = v;
    }
}

segtree nhaya, bdaya;
int ans, startNode[N], endNode[N], s[N];
vector<pair<int, pair<int, int>>> vec;

void collect(int u, int par, int val, int bestNhaya, int bestBdaya) {

    // start
    if(s[u] > val) {
        ans = max(ans, bestNhaya + 1 + startNode[u]);
    }
    // end
    if(s[u] < val) {
        ans = max(ans, endNode[u] + 1 + bestBdaya);
    }

    ans = max(ans, endNode[u] + bdaya.query(s[u] + 1, N - 1).len);
    ans = max(ans, nhaya.query(0, s[u] - 1).len + startNode[u]);

    vec.push_back({s[u], {startNode[u], endNode[u]}});

    for (auto v: adj[u]) {
        if (v == par)continue;
        collect(v, u, val, bestNhaya, bestBdaya);
    }
}

void reset(int u, int par) {
    bdaya.update(s[u], -1);
    nhaya.update(s[u], -1);
    for (auto v: adj[u]) {
        if (v == par)continue;
        reset(v, u);
    }
}

void dfs(int u, int par, bool keep) {
    for (auto v: adj[u]) {
        if (v == par || v == big[u])continue;
        dfs(v, u, false);
    }
    if (~big[u]) {
        dfs(big[u], u, true);
    }


    for (auto v: adj[u]) {
        if (v == par || v == big[u])continue;
        vec.clear();

        collect(v, u, s[u], nhaya.query(0, s[u] - 1).len, bdaya.query(s[u] + 1, N - 1).len);
        for(auto val : vec) {
            bdaya.update(val.first, val.second.first);
            nhaya.update(val.first, val.second.second);
        }
    }

    startNode[u] = bdaya.query(s[u] + 1, N - 1).len + 1;
    endNode[u] = nhaya.query(0, s[u] - 1).len + 1;

    ans = max(ans, startNode[u]);
    ans = max(ans, endNode[u]);

    bdaya.update(s[u], startNode[u]);
    nhaya.update(s[u], endNode[u]);

    // reset
    if (!keep) {
        reset(u, par);
    }
}

void solve() {
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> s[i];
    }
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    memset(big, -1, sizeof big);
    dfsSz(0, 0);
    bdaya.init(N);
    nhaya.init(N);
    dfs(0, 0, true);

    cout << ans;
}

signed main() {
    Drakon();
    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }
}