#include <cstdio>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;

inline int countPopulation(unsigned int x) {
	x -= ((x >> 1) & 0x55555555);
	x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
	x = ((x >> 4) + x) & 0x0f0f0f0f;
	x += (x >> 8);
	x += (x >> 16);
	return (x & 0x0000003f);
}

inline int countLeadingZero(unsigned int x) {
	x |= (x >> 1);
	x |= (x >> 2);
	x |= (x >> 4);
	x |= (x >> 8);
	x |= (x >> 16);
	return 32 - countPopulation(x);
}


typedef int rmq_t;

struct StaticRangeMinimumQuery : vector<rmq_t> {
	vector< vector<int> > sparseTable;

	StaticRangeMinimumQuery(){}

	template<class T>
	StaticRangeMinimumQuery(T first, T last):
		vector<rmq_t>(first, last)
	{}

	inline bool cmp(const rmq_t& lhs, const rmq_t& rhs){
		return lhs < rhs;
	}

	void build() {
		const int sz = size();
		const int logSize = 31 - countLeadingZero(sz);

		sparseTable.resize(logSize + 1);
		for (int i = 0; i <= logSize; ++i) {
			sparseTable[i].resize(sz - (1<<i) + 1);
		}

		for (int i = 0; i < sz; ++i) {
			sparseTable[0][i] = i;
		}

		for (int i = 0; i < logSize; ++i) {
			for (int j = 0, stopper = sz - (1<<(i+1)) + 1; j < stopper; ++j) {
				const int small = sparseTable[i][j],
						large = sparseTable[i][j+(1<<i)];
				sparseTable[i+1][j] = cmp(operator[](large), operator[](small)) ? large : small;
			}
		}
	}

	//[from, to)
	int getIndex(int from, int to) {
		const int logLength = 31 - countLeadingZero(to - from);
		const int small = sparseTable[logLength][from],
				large = sparseTable[logLength][to - (1<<logLength)];
		return cmp(operator[](large), operator[](small)) ? large : small;
	}

	//[from, to)
	rmq_t getValue(int from, int to) {
		return operator[](getIndex(from, to));
	}
};


struct Edge {
	int to;

	Edge(){}
	Edge(int to_):
		to(to_)
	{}
};


struct Node {
	pair<int,int> value; //(value, index)
	int size;
	bool isValid;
	Node *child[2];//0:left, 1:right
	Node(){}
	Node(int val, int index, bool valid):
		value(val, index), size(valid?1:0), isValid(valid)
	{
		child[0] = child[1] = 0;
	}
};

Node *getNode(int val, int index, bool valid) {
	return new Node(val, index, valid);
}

Node *copyNode(Node *v) {
	Node *ret = new Node;
	*ret = *v;
	return ret;
}

int getSize(Node *r) {
	return r ? r->size : 0;
}

struct Graph : vector< vector<Edge> > {
	int numV;
	vector<int> xs;
	StaticRangeMinimumQuery depth;
	vector<int> stamp, eulerTour, parent;
	vector<Node*> tree;

	Graph(){}

	void init(int numV_) {
		numV = numV_;
		init();
	}

	void init() {
		assign(numV, vector<Edge>());
		xs.assign(numV, 0);
	}

	void addUndirectedEdge(int from, int to) {
		at(from).push_back(Edge(to));
		at(to).push_back(Edge(from));
	}

	void addDirectedEdge(int from, int to) {
		at(from).push_back(Edge(to));
	}

	void buildLowestCommonAncestor(int root) {
		depth.resize(2*numV - 1);
		eulerTour.resize(2*numV - 1);
		stamp.assign(numV, -1);
		parent.assign(numV, -1);

		vector< pair<int, int> > stack; 
		stack.reserve(numV);
		int curDepth = 0, counter = 0;
		stack.push_back( make_pair(root, 0) );

		for (;!stack.empty();) {
			int v = stack.back().first, start = stack.back().second;
			stack.pop_back();
			if (start == 0) {
				stamp[v] = counter;
			}
			eulerTour[counter] = v;
			depth[counter] = curDepth;
			++counter;

			for (int i = start; i < (int)operator[](v).size(); ++i) {
				const int u = operator[](v)[i].to;
				if (stamp[u] == -1) {
					parent[u] = v;
					stack.push_back( make_pair(v, i + 1) );
					stack.push_back( make_pair(u, 0) );
					curDepth += 2;
					break;
				}
			}
			--curDepth;
		}

		depth.build();
	}

	int getLCA(int v, int u) {
		if (stamp[v] > stamp[u]) {
			std::swap(v, u);
		}
		return eulerTour[depth.getIndex(stamp[v], stamp[u] + 1)];

	}

	Node *buildInit(const vector<pair<int,int> >& nums, int from, int to) {
		if (to - from <= 0) {
			return 0;
		}
		if (to - from == 1) {
			return getNode(nums[from].first, nums[from].second, false);
		}
		int mid = (from + to) / 2;
		Node *ret = getNode(nums[mid].first, nums[mid].second, false);
		ret->child[0] = buildInit(nums, from, mid);
		ret->child[1] = buildInit(nums, mid + 1, to);
		return ret;
	}

	Node *insertPersistent(Node *pTree, pair<int,int> val) {
		Node *ret = copyNode(pTree);
		if (ret->value == val) {
			ret->isValid = true;
		}
		else if (val < ret->value) {
			ret->child[0] = insertPersistent(pTree->child[0], val);
		}
		else {
			ret->child[1] = insertPersistent(pTree->child[1], val);
		}
		ret->size = ret->isValid ? 1 : 0;
		for (int i = 0; i < 2; ++i) {
			ret->size += getSize(ret->child[i]);
		}
		return ret;
	}

	void buildPersistenseBST() {
		vector< pair<int,int> > nums(numV - 1);
		for (int i = 1; i < numV; ++i) {
			nums[i-1] = make_pair(xs[i], i);
		}
		sort(nums.begin(), nums.end());
		tree.resize(numV);
		tree[0] = buildInit(nums, 0, nums.size());
		stack<int> stack;
		stack.push(1);
		for (;!stack.empty();) {
			int v = stack.top(); stack.pop();
			for (int i = 0; i < int(operator [](v).size()); ++i) {
				int u = operator[](v)[i].to;
				if (u != parent[v]) {
					stack.push(u);
				}
			}
			tree[v] = insertPersistent(tree[parent[v]], make_pair(xs[v], v));
		}
	}

};

int main() {
	int n, q;
	scanf("%d%d", &n, &q);
	Graph g;
	g.init(n + 1);
	for (int i = 0; i < n; ++i) {
		scanf("%d", &g.xs[i+1]);
	}
	g.addUndirectedEdge(0, 1);
	for (int i = 0; i < n - 1; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		g.addUndirectedEdge(x, y);
	}
	g.buildLowestCommonAncestor(0);
	g.buildPersistenseBST();
	for (int _ = 0; _ < q; ++_) {
		int w, v, l;
		scanf("%d%d%d", &w, &v, &l);
		--l;
		int lca = g.getLCA(w, v), par = g.parent[lca];
		Node *wp = g.tree[w], *vp = g.tree[v], *lp = g.tree[lca], *pp = g.tree[par];
		for (;;) {
			int left = getSize(wp->child[0])+getSize(vp->child[0])-getSize(lp->child[0])-getSize(pp->child[0]);
			int valid = (wp->isValid || vp->isValid) && !pp->isValid;
			int which = left + valid <= l;
			if (left == l && valid) {
				printf("%d\n", wp->value.first);
				break;
			}
			if (which) {
				l -= left + valid;
			}
			wp = wp->child[which];
			vp = vp->child[which];
			lp = lp->child[which];
			pp = pp->child[which];
		}
	}

	return 0;
}

Measured memory_bytes: 102124