#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>
#include<utility>
#include<cstring>
#include<cstdlib>
using namespace std;



inline int popCount(unsigned int x) {
#ifdef _WIN32
	x = x - (( x >> 1 ) & 0x55555555);
	x = (x & 0x33333333) + (( x >> 2) & 0x33333333);
	x = ( x + ( x >> 4 )) & 0x0F0F0F0F;
	x = x + ( x >> 8 );
	x = x + ( x >> 16 );
	return x & 0x0000003F;
#else
	return __builtin_popcount(x);
#endif
}

inline int kthRightmostPop(unsigned int pop1,int k){
	unsigned int pop2,pop4,pop8,pop16;
	int pos=0;
	pop2 = (pop1>>1 & 0x55555555)+(pop1 & 0x55555555);
	pop4 = (pop2>>2 & 0x33333333)+(pop2 & 0x33333333);
	pop8 = (pop4>>4 & 0x0f0f0f0f)+(pop4 & 0x0f0f0f0f);
	pop16= (pop8>>8 & 0x00ff00ff)+(pop8 & 0x00ff00ff);
	if((pop16    &0x0000ffff) < k){
		k -= (pop16    &0x0000ffff);
		pos |= 16;
	}
	if((pop8>>pos&0x000000ff) < k){
		k -= (pop8>>pos&0x000000ff);
		pos |= 8;
	}
	if((pop4>>pos&0x0000000f) < k){
		k -= (pop4>>pos&0x0000000f);
		pos |= 4;
	}
	if((pop2>>pos&0x00000003) < k){
		k -= (pop2>>pos&0x00000003);
		pos |= 2;
	}
	if((pop1>>pos&0x00000001) < k)pos |= 1;
	return pos;
}



//メモリ使用量:2nビット
class BitVector{
	int n;
	int blocks;
	vector<unsigned int> B;
	vector<int> r;
public:
	BitVector(){}
	BitVector(int size){
		init(size);
	}
	void init(int size){
		n = size;
		blocks = (n>>5)+1;
		B.assign(blocks ,0);
		r.assign(blocks ,0);
	}
	void set(int k){
		B[k>>5] |= 1<<(k&31);
	}
	void build(){
		r[0]=0;
		for(int i=1;i<blocks;i++){
			r[i] = popCount(B[i-1]) + r[i-1];
		}
	}	
	bool access(int k)const{
		return B[k>>5] & 1<<(k&31);
	}
	//[0,k)の1の個数
	int rank(int k)const{
		return r[k>>5] + popCount(B[k>>5] & ((1<<(k&31))-1));
	}
	//k番目の１の場所(1<=k)
	//O(log n)
	int select1(int k)const{
		int lb=0,ub=blocks;
		if(k==0)return -1;
		while(ub-lb>1){
			int m = (lb+ub)/2;
			if(k<=r[m])ub=m;
			else lb=m;
		}
		k -= r[lb];
		return lb<<5 | kthRightmostPop(B[lb],k);
	}
	//O(log n)
	int select0(int k)const{
		int lb=0,ub=blocks;
		if(k==0)return -1;
		while(ub-lb>1){
			int m = (lb+ub)/2;
			if(k<=(m<<5)-r[m])ub=m;
			else lb=m;
		}
		k -= (lb<<5)-r[lb];
		return lb<<5 | kthRightmostPop(~B[lb],k);
	}
};



class SignedWaveletMatrix{
	typedef int Val;
	static const Val NIL=-1;
	static const int BITLEN = 30;
	int len;
	BitVector bv[BITLEN];
	BitVector mzero[BITLEN],mone[BITLEN];//minus
	int encode(Val c)const{
		return c;
	}
	Val decode(int n)const{
		return n;
	}
	struct Node{
		int height,s,e,code;
		Node(){}
		Node(int a,int b,int c,int d):height(a),s(b),e(c),code(d){};
		bool operator <(Node a)const{return e-s<a.e-a.s;}
	};
public:
	SignedWaveletMatrix(const vector<Val> &str,const vector<int> &sign){
		init(str,sign);
	}
	//O(n logσ)
	void init(const vector<Val> &str,const vector<Val> &sign){//1:plus,0minus
		len = str.size();
		for(int i=0;i<BITLEN;i++){
			bv[i].init(str.size());
			mone[i].init(str.size());
			mzero[i].init(str.size());
		}
		pair<int,bool> *bucket;
		bucket = new pair<int,bool>[2*len];
		pair<int,bool> *cur,*next;
		cur = bucket;
		next = bucket+len;
		int rank0[BITLEN]={0};
		for(int i=0;i<len;i++){
			int n = encode(str[i]);
			cur[i].first = n;
			cur[i].second = sign[i];
			for(int j=BITLEN-1;j>=0;j--){
				if((n&1<<j)==0)rank0[j]++;
			}
		}
		for(int i=BITLEN-1;;i--){
			for(int j=0;j<len;j++){
				if(cur[j].first&1<<i)bv[i].set(j);
				if(!cur[j].second){
					if(cur[j].first&1<<i)mone[i].set(j);
					else mzero[i].set(j);
				}
			}
			bv[i].build();
			mone[i].build();
			mzero[i].build();
			if(i==0)break;
			int idx0=0,idx1=rank0[i];
			for(int j=0;j<len;j++){
				if(cur[j].first&1<<i)next[idx1++]=cur[j];
				else next[idx0++]=cur[j];
			}
			swap(cur,next);
		}
		delete[] bucket;
	}
	Val kthSmallest(int s,int e,int k)const{
		int code=0;
		for(int i=BITLEN-1;i>=0;i--){
			if(s==e)return NIL;
			int ssum = bv[i].rank(s);
			int esum = bv[i].rank(e);
			int num1 = esum-ssum;
			int num0 = e-s-num1;
			num0-=2*(mzero[i].rank(e)-mzero[i].rank(s));
			if(k<num0){
				s = s-ssum;
				e = e-esum;
			}else{
				code |= 1<<i;
				k-=num0;	
				s = len-bv[i].rank(len) + ssum;
				e = s + num1;
			}
		}
		return decode(code);
	}
	Val kthSmallest(int s,int e,int u,int v,int k)const{
		int code=0;
		for(int i=BITLEN-1;i>=0;i--){
			int n=0;
			if(s!=e){
				int ssum = bv[i].rank(s);
				int esum = bv[i].rank(e);
				int num1 = esum-ssum;
				int num0 = e-s-num1;
				num0-=2*(mzero[i].rank(e)-mzero[i].rank(s));
				n += num0;
			}
			if(u!=v){
				int ssum = bv[i].rank(u);
				int esum = bv[i].rank(v);
				int num1 = esum-ssum;
				int num0 = v-u-num1;
				num0-=2*(mzero[i].rank(v)-mzero[i].rank(u));
				n += num0;
			}

			if(k<n){
				if(s!=e){
					int ssum = bv[i].rank(s);
					int esum = bv[i].rank(e);
					s = s-ssum;
					e = e-esum;
				}
				if(u!=v){
					int ssum = bv[i].rank(u);
					int esum = bv[i].rank(v);
					u = u-ssum;
					v = v-esum;
				}
			}else{
				code |= 1<<i;
				k-=n;
				if(s!=e){
					int ssum = bv[i].rank(s);
					int esum = bv[i].rank(e);
					int num1 = esum-ssum;
					s = len-bv[i].rank(len) + ssum;
					e = s + num1;
				}
				if(u!=v){
					int ssum = bv[i].rank(u);
					int esum = bv[i].rank(v);
					int num1 = esum-ssum;
					u = len-bv[i].rank(len) + ssum;
					v = u + num1;
				}
			}
		}
		return decode(code);
	}
};




class LCA{
	int lg,n;
	std::vector<int> depth,par;
	int dfs(const int parent[],int u){
		if(parent[u]==-1)return depth[u]=1;
		if(depth[u]!=0)return depth[u];
		return depth[u]=dfs(parent,parent[u])+1;
	}
public:
	LCA(const int parent[],int n):n(n),depth(n,0){
		lg=1;
		while((1<<lg)<n)lg++;
		lg++;
		for(int i=0;i<n;i++)dfs(parent,i);
		par.resize(n*lg);	
		for(int i=0;i<n;i++)par[i]=parent[i];
		for(int i=1;i<lg;i++)
			for(int v=0;v<n;v++)
				if(par[(i-1)*n+v]!=-1)par[i*n+v]=par[(i-1)*n+par[(i-1)*n+v]];
				else par[i*n+v]=-1;
	}
	int query(int u,int v)const{
		if(depth[u] > depth[v])std::swap(u,v);
		for(int i=lg-1;i>=0;i--)
			if(depth[u] <= depth[v]-(1<<i))
				v=par[i*n+v];
		if(u==v)return u;
		for(int i=lg-1;i>=0;i--){
			if(par[i*n+u]!=par[i*n+v]){
				u=par[i*n+u];
				v=par[i*n+v];
			}
		}
		return par[u];
	}
	int depth_vertex(int u)const{
		return depth[u];
	}
};


vector<vector<int> > edges;

vector<int> nodeID;
vector<int> sign;
bool used[100000];
int par[100000];

void dfs(int p,int u){
	if(used[u])return;
	used[u]=true;

	par[u]=p;
	nodeID.push_back(u);
	sign.push_back(1);

	vector<int> &e=edges[u];
	for(int i=0;i<e.size();i++){
		dfs(u,e[i]);
	}
	nodeID.push_back(u);
	sign.push_back(0);
}




int main(){
	int n,q;
	vector<int> a;
	cin>>n>>q;
	a.resize(n);
	for(int i=0;i<n;i++)cin>>a[i];
	edges.resize(n);
	for(int i=0;i<n-1;i++){
		int a,b;
		cin>>a>>b;
		a--;b--;
		edges[a].push_back(b);
		edges[b].push_back(a);
	}
	memset(par,-1,sizeof(par));
	dfs(-1,0);


	LCA ancestor(par,n);
	vector<int> pos(n);
	for(int i=2*n-1;i>=0;i--){
		pos[nodeID[i]]=i;
	}


	vector<int> val(n*2);
	for(int i=0;i<n*2;i++){
		val[i]=a[nodeID[i]];
	}

	SignedWaveletMatrix wm(val,sign);
	for(int i=0;i<q;i++){
		int u,v,k;
		cin>>u>>v>>k;
		u--;v--;k--;
		int lca=ancestor.query(u,v);

		int ans;
		if(v==lca){
			ans=wm.kthSmallest(pos[lca],pos[u]+1,k);
		}else if(u==lca){
			ans=wm.kthSmallest(pos[lca],pos[v]+1,k);
		}else{
			ans=wm.kthSmallest(pos[lca],pos[u]+1,
				pos[lca]+1,pos[v]+1,k);
		}
		cout<<ans<<endl;
	}
	return 0;
}

Measured memory_bytes: 28808