这题和普通的第K大类似。
普通的第K大,是从后往前建立主席树,前一个在后一个的基础上修改。
而树上第K大,依旧是每个结点一棵主席树,是在父节点的基础上修改。
那么可以发现这棵主席树是包括所有祖先结点的(就是深度在当前结点之上的)
查询的时候,是两个结点的值的和,还要减掉lca以上的部分。同时要注意处理lca这个 结点的值。
主要不同便是建树是根据父结点,以前查询的时候注意两个主席树的公共部分。

#include<bits/stdc++.h>
#define M 10000005
#define N 110005
using namespace std;

int n, q, a[N];
vector<int> edge[N];
int t[N], m;

void Init_hash()
{
    for (int i = 1; i <= n; i++)
        t[i] = a[i];
    sort(t + 1, t + 1 + n);
    m = unique(t + 1, t + 1 + n) - t - 1;
}

int Hash(int x)
{
    return lower_bound(t + 1, t + 1 + m, x) - t;
}
int T[M], lson[M], rson[M], c[M], tot = 0;

int bulid(int l, int r)
{
    int root = tot++;
    c[root] = 0;
    if (l != r)
    {
        int mid = (l + r) >> 1;
        lson[root] = bulid(l, mid);
        rson[root] = bulid(mid + 1, r);
    }
    return root;
}

int update(int root, int pos, int val)
{
    int newroot = tot++, tmp = newroot;
    c[newroot] = c[root] + val;
    int l = 1, r = m;
    while (l < r)
    {
        int mid = (l + r) >> 1;
        if (pos <= mid)
        {
            lson[newroot] = tot++;
            rson[newroot] = rson[root];
            newroot = lson[newroot];
            root = lson[root];
            r = mid;
        }
        else
        {
            rson[newroot] = tot++;
            lson[newroot] = lson[root];
            newroot = rson[newroot];
            root = rson[root];
            l = mid + 1;
        }
        c[newroot] = c[root] + val;
    }
    return tmp;
}

int query(int left_root, int right_root, int LCA, int k)
{
    int lca_root = T[LCA], pos = Hash(a[LCA]);
    int l = 1, r = m;
    while (l < r)
    {
        int mid = (l + r) >> 1;
        int t = c[lson[left_root]] + c[lson[right_root]] - 2 * c[lson[lca_root]] + (pos >= l && pos <= mid);
        if (t >= k)
        {
            left_root = lson[left_root];
            right_root = lson[right_root];
            lca_root = lson[lca_root];
            r = mid;
        }
        else
        {
            k -= t;
            left_root = rson[left_root];
            right_root = rson[right_root];
            lca_root = rson[lca_root];
            l = mid + 1;
        }
    }
    return l;
}
/*              主席树部分           */
/*              LCA部分            */
int depth = 0, b[N * 2], cnt = 0;
int p[N], f[N];

void dfs(int u, int pre)
{
    int t = ++depth;
    b[++cnt] = t;
    f[t] = u;
    p[u] = cnt;
    T[u] = update(T[pre], Hash(a[u]), 1);
    for (int i = 0; i < edge[u].size(); i++)
    {
        int v = edge[u][i];
        if (v == pre)
            continue;
        dfs(v, u);
        b[++cnt] = t;
    }
}
int dp[N * 2][20];
void Init_rmq(int n)
{
    for (int i = 1; i <= n; i++)
        dp[i][0] = b[i];
    int m = floor(log(n * 1.0) / log(2.0));
    for (int j = 1; j <= m; j++)
        for (int i = 1; i <= n - (1 << j) + 1; i++)
            dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}

int rmq(int l, int r)
{
    int k = floor(log((r - l + 1) * 1.0) / log(2.0));
    return min(dp[l][k], dp[r - (1 << k) + 1][k]);
}

int lca(int a, int b)
{
    if (p[a] > p[b])
        swap(a, b);
    return f[rmq(p[a], p[b])];
}
/*              LCA部分            */
int main()
{
    scanf("%d",&n);
    scanf("%d",&q);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d",&u);
        scanf("%d",&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    Init_hash();
    T[0] = bulid(1, m);
    dfs(1, 0);
    Init_rmq(cnt);
    while (q--)
    {
        int u, v, k;
        scanf("%d",&u);
        scanf("%d",&v);
        scanf("%d",&k);
        printf("%d\n", t[query(T[u], T[v], lca(u, v), k)]);
    }
    return 0;
}