#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <functional>
#include <cassert>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define pb push_back
#define eb emplace_back
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

const int INF = 1<<28;
const double EPS = 1e-8;
const int MOD = 1000000007;

class LCA{
	int n;
	vector<vi> parent;
	vector<int> depth;
	ll ans;
	int maxdepth;
	
public:
	LCA(vector<vi> &g, int root) {
		n=g.size();
		maxdepth = 0;
		while(n>>maxdepth) maxdepth ++;
		
		parent = vector< vector<int> >(maxdepth+1, vector<int>(n));
		depth = vector<int>(n);
		
		parent[0][0] = -1;
		queue<pii> que;
		que.emplace(root, -1);
		while(!que.empty()){
			const int r = que.front().first;
			const int p = que.front().second;
			que.pop();
			depth[r] = p==-1 ? 0 : depth[p]+1;
			parent[0][r] = p;
			REP(i, g[r].size()) if(g[r][i] != p) que.emplace(g[r][i], r);
		}
		
		REP(k, maxdepth){
			REP(i, n){
				if(parent[k][i] < 0) parent[k+1][i] = -1;
				else parent[k+1][i] = parent[k][parent[k][i]];
			}
		}
	}
	
	ll lca(int u, int v){
		if(depth[u] > depth[v]) swap(u, v);
		ll ans = 0;
		REP(k, maxdepth+1){
			if((depth[v]-depth[u])>>k&1){
				v = parent[k][v];
			}
		}
		if(u==v) return u;
		RREP(k, maxdepth+1){
			if(parent[k][u] != parent[k][v]){
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
	
	inline int par(int u){return parent[0][u];}
};

struct handler_sum{
	typedef int val_t;
	typedef int opr_t;
	handler_sum(){}
	val_t def_val(){ return 0; }
	inline static val_t update(const val_t &l, const opr_t &r){
		return l + r;
	}
	inline static val_t update_overwrite(const val_t &l, const val_t &r){
		return r;
	}
	inline static val_t merge(const val_t &l, const val_t &r){
		return l + r;
	}
};

template<typename Handler>
struct SegTreePersistent{
	typedef typename Handler::val_t val_t;
	typedef typename Handler::opr_t opr_t;
	struct Node{
		int lch, rch;
		val_t val;
		Node(val_t val):val(val){lch = rch = 0;}
	};
	vector<Node> node;
	Handler hdl;
	int n;
	
	SegTreePersistent(int size):hdl(){
		n = size;
		node.resize(2, hdl.def_val());	// dummy & root
	}
	int update(int i, opr_t x, int k,int l,int r){
		if(r<=i||i<l) return k;
		node.pb(node[k]);
		k = (int)node.size()-1;
		if(r-l == 1){
			node[k].val = hdl.update(node[k].val, x);
			return k;
		}
		int lch = update(i, x, node[k].lch, l, (l+r)/2);
		int rch = update(i, x, node[k].rch, (l+r)/2, r);
		node[k].lch = lch;node[k].rch = rch;
		node[k].val = hdl.merge(node[lch].val, node[rch].val);
		return k;
	}
	val_t query(int a,int b,int k,int l,int r){
		if(r<=a||b<=l||!k) return hdl.def_val();
		if(a<=l&&r<=b) return node[k].val;
		return hdl.merge(query(a, b, node[k].lch, l, (l+r)/2),
					     query(a, b, node[k].rch, (l+r)/2, r)
					    );
	}
	int update(int i, opr_t x, int root=1){return update(i, x, root, 0, n);}
	val_t query(int a, int b, int root=1){return query(a, b, root, 0, n);}
};

int n, m;
int a[100001];
int root[100001];
vector<vi> g;

template <typename T=int>
struct Zipper{
	vector<T> dec;
	unordered_map<T, int> enc;
	Zipper(){}
	inline void add(T t){dec.pb(t);}
	inline size_t size(){return dec.size();}
	void compile(){
		sort(ALL(dec)); UNIQUE(dec);
		REP(i, dec.size()) enc[dec[i]] = i;
	}
	inline T operator[](int i){return dec[i];}
	inline T operator()(T t){return enc[t];}
	inline int lb(T t){return lower_bound(ALL(dec), t) - dec.begin();}
	inline int ub(T t){return upper_bound(ALL(dec), t) - dec.begin();}
};


int main(int argc, char *argv[]){
	scanf("%d%d", &n, &m);
	g.resize(n+1);
	Zipper<int> zip;
	REP(i, n){
		scanf("%d", &a[i+1]);
		zip.add(a[i+1]);
	}
	zip.compile();
	REP(i, n) a[i+1] = zip(a[i+1]);
	REP(i, n-1){
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v);
		g[v].pb(u);
	}
	g[0].push_back(1);
	g[1].push_back(0);
	LCA lca(g, 0);
	SegTreePersistent<handler_sum> seg(zip.size());
	root[0] = 1;
	queue<pii> que;
	que.emplace(1, 0);
	while(!que.empty()){
		const int r = que.front().first;
		const int p = que.front().second;
		que.pop();
		root[r] = seg.update(a[r], 1, root[p]);
		FOR(v, g[r])if(*v!=p) que.emplace(*v, r);
	}
	REP(i, m){
		int v, w, k;
		scanf("%d%d%d", &v, &w, &k);
		int u = lca.lca(v, w);
		int t = lca.par(u);
		t = root[t];u = root[u];
		v = root[v];w = root[w];
		int l = 0, r = zip.size();
		while(l+1<r){
			int lk = seg.node[seg.node[v].lch].val + seg.node[seg.node[w].lch].val
				   - seg.node[seg.node[u].lch].val - seg.node[seg.node[t].lch].val;
			if(lk < k){
				k -= lk;
				l = l + ((r-l)>>1);
				t = seg.node[t].rch;
				u = seg.node[u].rch;
				v = seg.node[v].rch;
				w = seg.node[w].rch;
			}else{
				r = l + ((r-l)>>1);
				t = seg.node[t].lch;
				u = seg.node[u].lch;
				v = seg.node[v].lch;
				w = seg.node[w].lch;
			}
		}
		printf("%d\n", zip[l]);
	}
	return 0;
}

Measured memory_bytes: 46376