#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int SIZE = 1 << 18;
const int LOGN = 18;
struct SegmentTree {
    int node[2*SIZE];
    SegmentTree() { fill(node, node + 2*SIZE, 0); }
    void reset() { fill(node, node + 2*SIZE, 0); }
    void update(int x, int d) {
        x += SIZE - 1;
        node[x] += d;
        while(x > 0) {
            x = (x - 1) / 2;
            node[x] = node[2*x+1] + node[2*x+2];
        }
    }
    int query(int a, int b, int l=0, int r=SIZE, int k=0) {
        if(b <= l || r <= a) return 0;
        if(a <= l && r <= b) return node[k];
        int mid = (l + r) / 2;
        int vl = query(a, b, l, mid, 2*k+1);
        int vr = query(a, b, mid, r, 2*k+2);
        return vl + vr;
    }
};

int euler_t[2*SIZE], start_v[SIZE], depth[SIZE], par[SIZE][LOGN + 1];
vector<int> posi[SIZE], nega[SIZE], G[SIZE];

void eulertour(int cur, int p=-1) {
    static int idx = 0, dep = 0;
    start_v[cur] = idx;
    euler_t[idx] = cur;
    depth[cur] = dep;
    posi[cur].push_back(idx++);
    for(auto to : G[cur]) {
        if(to == p) continue;
        par[to][0] = cur; dep++;
        eulertour(to, cur);
        euler_t[idx] = cur; dep--;
        nega[ euler_t[idx - 1] ].push_back(idx);
        idx++;
    }
}

struct Query {
    int u, v, lth, ub, lb, idx;
    int get_mid() { return (ub + lb) / 2; }
    Query() {}
    Query(int a, int b, int c, int d, int e, int f) :
        u(a), v(b), lth(c), ub(d), lb(e), idx(f) {}
    bool operator<(const Query &q) const {
        return (ub + lb) / 2 < (q.ub + q.lb) / 2;
    }
};

int get_lca(int u, int v) {
    // fprintf(stderr, "call: u = %d, v = %d\n", u, v);
    if(depth[u] < depth[v]) swap(u, v);
    int dep_diff = depth[u] - depth[v];
    for(int k=LOGN; k>=0; k--) {
        if(dep_diff >> k & 1) u = par[u][k];
    }
    // fprintf(stderr, "current: u = %d, v = %d\n", u, v);
    if(u == v) return u;
    for(int k=LOGN; k>=0; k--) {
        if(par[u][k] != par[v][k]) {
            u = par[u][k];
            v = par[v][k];
        }
    }
    return par[u][0];
}

SegmentTree seg;
int main() {
    int N, Q; cin >> N >> Q;
    fill(par[0], par[N], -1);
    
    vector< pair<int, int> > vertex_val;
    for(int i=0; i<N; i++) {
        int val; cin >> val;
        vertex_val.push_back(make_pair(val, i));
    }
    sort(vertex_val.begin(), vertex_val.end());

    for(int i=0; i<N-1; i++) {
        int u, v; cin >> u >> v;
        u--; v--;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    eulertour(0);

    for(int k=1; k<LOGN; k++) {
        for(int i=0; i<N; i++) {
            if(par[i][k-1] < 0) par[i][k] = -1;
            else par[i][k] = par[ par[i][k-1] ][k-1];
            // fprintf(stderr, "par[%d][%d] = %d\n", i, k, par[i][k]);
        }
    }

    /*
    for(int i=0; i<2*N-1; i++) {
        cout << euler_t[i] << " ";
    }
    cout << endl;
    for(int i=0; i<N; i++) {
        cout << endl << "vertex " << i+1 << "(start_v = " << start_v[i] << ", depth = " << depth[i] << ")";
        cout << endl << "posi:"; for(auto x : posi[i]) cout << " " << x;
        cout << endl << "nega:"; for(auto x : nega[i]) cout << " " << x;
    }
    cout << endl;
    */

    vector<Query> queries(Q);
    for(int i=0; i<Q; i++) {
        int u, v, lth; cin >> u >> v >> lth;
        u--; v--;
        queries[i] = Query(u, v, lth, N-1, -1, i);
    }

    for(int z=0; z<LOGN; z++) {
        seg.reset();
        int idx = 0;
        for(int i=0; i<Q; i++) {
            if(queries[i].ub - queries[i].lb == 1) continue;
            for(; idx <= queries[i].get_mid() ; idx++) {
                int v_id = vertex_val[idx].second;
                for(auto x : posi[v_id]) seg.update(x,  1);
                for(auto x : nega[v_id]) seg.update(x, -1);
            }
            // fprintf(stderr, "mid = %d\n", queries[i].get_mid());
            int u = queries[i].u, v = queries[i].v;
            if(start_v[u] > start_v[v]) swap(u, v);
            int LCA = get_lca(u, v);
            // fprintf(stderr, "lca of %d and %d = %d\n", u, v, LCA);
            int val = seg.query(start_v[LCA], start_v[u] + 1) + seg.query(start_v[LCA], start_v[v] + 1) - seg.query(start_v[LCA], start_v[LCA] + 1);
            // fprintf(stderr, "query <<%d %d %d>> [%d, %d) idx = %d, proceed = %d, val = %d, lth = %d\n", queries[i].u, queries[i].v, queries[i].lth, start_v[u], start_v[v] + 1, i, idx, val, queries[i].lth);
            if(val < queries[i].lth) {
                queries[i].lb = queries[i].get_mid();
            }
            else {
                queries[i].ub = queries[i].get_mid();
            }
        }
        sort(queries.begin(), queries.end());
    }

    vector<int> ans(Q);
    for(int i=0; i<Q; i++) {
        // fprintf(stderr, "query idx = %d, ub = %d, lb = %d\n", queries[i].idx, queries[i].ub, queries[i].lb);
        ans[ queries[i].idx ] = vertex_val[ queries[i].ub ].first;
    }
    for(int i=0; i<Q; i++) {
        // if(i < 0 || i >= N) fprintf(stderr, "i = %d\n", i);
        cout << ans[i] << endl;
    }
    return 0;
}


Measured memory_bytes: 48864