#include<bits/stdc++.h>
using namespace std;
struct SegmentTree {
  int n;
  vector< vector< int > > data;
  SegmentTree(int sz, vector< int >& d){
    n = 1;
    while(n < sz) n *= 2;
    data.resize(2 * n + 1);
    for(int i = 0; i < sz; i++) {
      data[i + n - 1].push_back(d[i]);
    }
    for(int i = n - 2; i >= 0; i--) {
      data[i].resize(data[2 * i + 1].size() + data[2 * i + 2].size());
      merge(data[2 * i + 1].begin(), data[2 * i + 1].end(), data[2 * i + 2].begin(), data[2 * i + 2].end(), data[i].begin());
    }
  }
  int Query(int a, int b, int x, int k, int l, int r) { // [a,b)??§x??\???????????°?????????
    if(a >= r || b <= l) return(0);
    if(a <= l && r <= b) return(upper_bound(data[k].begin(), data[k].end(), x) - data[k].begin());
    return(Query(a, b, x, 2 * k + 1, l, (l + r) >> 1) + Query(a, b, x, 2 * k + 2, (l + r) >> 1, r));
  }
  int Query(int a, int b, int x) {
    return(Query(a, b, x, 0, 0, n));
  }
};
struct Node {
  int ParIdx, ParDepth, Deep; // Deep: HeavyEdge?????§?????±???
  int Size;
};
typedef vector< vector< int > > Graph;

int N, Q, x[100000];
Graph graph;
int treesz[100000], sz;
Node nodes[100000];
int nowtreeIdx[100000], nowtreeDepth[100000]; 
vector< int > Nodes[100000];
vector< SegmentTree > segs;

int sizeDFS(int idx, int prev) {
  treesz[idx] = 1;
  for(int i = 0; i < graph[idx].size(); i++) {
    if(graph[idx][i] != prev) treesz[idx] += sizeDFS(graph[idx][i], idx);
  }
  return(treesz[idx]);
}
void makeDFS(int idx, int prev, int treeIdx, int treeDepth, int ParDepth) {
  nodes[treeIdx].Size++;
  Nodes[treeIdx].push_back(x[idx]);
  nowtreeIdx[idx] = treeIdx;
  nowtreeDepth[idx] = treeDepth;
  int ret = 0;
  for(int i = 0; i < graph[idx].size(); i++) {
    if(graph[idx][i] != prev) ret = max(ret, treesz[graph[idx][i]]);
  }
  bool done = false;
  for(int i = 0; i < graph[idx].size(); i++) {
    if(graph[idx][i] != prev) {
      if(treesz[graph[idx][i]] == ret && !done++) {
        makeDFS(graph[idx][i], idx, treeIdx, treeDepth + 1, ParDepth);
      } else {
        nodes[sz++] = (Node){ treeIdx, treeDepth, ParDepth + 1, 0};
        makeDFS(graph[idx][i], idx, sz - 1, 0, ParDepth + 1);
      }
    }
  }
}
void HL() { // ??????????§£
  sizeDFS(0, -1);
  sz = 0;
  nodes[sz++] = (Node){ -1, -1, 0, 0};
  makeDFS(0, -1, 0, 0, 0);
  for(int i = 0; i < sz; i++) {
    segs.push_back(SegmentTree(nodes[i].Size, Nodes[i]));
  }
}
int main() {
  int N, Q;
  vector< int > nums;
  scanf("%d %d", &N, &Q);
  graph.resize(N);
  for(int i = 0; i < N; i++) {
    scanf("%d", &x[i]);
    nums.push_back(x[i]);
  }
  sort(nums.begin(), nums.end());
  nums.erase(unique(nums.begin(), nums.end()), nums.end());
  for(int i = 0; i < N; i++) {
    x[i] = lower_bound(nums.begin(), nums.end(), x[i]) - nums.begin();
  }

  for(int i = 0; i < N - 1; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    --a, --b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  HL();
  for(int i = 0; i < Q; i++) { // O(Q log^4 N)
    int v, w, l;
    scanf("%d %d %d", &v, &w, &l);
    --v, --w;
    int low = 0, high = N - 1;
    while(high - low > 0) {
      int mid = (high + low) >> 1;
      int Sum = 0;
      int TreeIdxA = nowtreeIdx[v], TreeDepthA = nowtreeDepth[v];
      int TreeIdxB = nowtreeIdx[w], TreeDepthB = nowtreeDepth[w];
      while(TreeIdxA != TreeIdxB) {
        if(nodes[TreeIdxA].Deep > nodes[TreeIdxB].Deep) {
          Sum += segs[TreeIdxA].Query(0, TreeDepthA + 1, mid);
          TreeDepthA = nodes[TreeIdxA].ParDepth;
          TreeIdxA   = nodes[TreeIdxA].ParIdx;
        } else {
          Sum += segs[TreeIdxB].Query(0, TreeDepthB + 1, mid);
          TreeDepthB = nodes[TreeIdxB].ParDepth;
          TreeIdxB   = nodes[TreeIdxB].ParIdx;
        }
      }
      if(TreeDepthA > TreeDepthB) swap(TreeDepthA, TreeDepthB);
      Sum += segs[TreeIdxA].Query(TreeDepthA, TreeDepthB + 1, mid);
      if(Sum >= l) high = mid;
      else low = mid + 1;
    }
    printf("%d\n", nums[low]);
  }
}

Measured memory_bytes: 53300