#include <iostream>
#include <utility>
#include <tuple>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <numeric>
#include <queue>
#include <cmath>
#include <iomanip>
#include <array>
#include <string>
#include <stack>
#include <cassert>
#include <memory>
#include <random>
template<typename T>
struct IndexedValue {
	int index;
	T value;
};
class MinSegmentTree {
	std::vector<std::vector<int>> vec;
	std::vector<std::vector<int>> min_index;
public:
	MinSegmentTree(const std::vector<int>& initial_state) : vec{ initial_state }, min_index{ std::vector<int>(initial_state.size()) } {
		std::iota(min_index[0].begin(), min_index[0].end(), 0);
		while (vec.back().size() > 1) {
			std::vector<int> last(vec.back().size() >> 1);
			std::vector<int> last_index(min_index.back().size() >> 1);
			for (auto i = 0; i < last.size(); ++i) {
				if (vec.back()[i << 1] <= vec.back()[(i << 1) + 1]) {
					last_index[i] = 1 << i;
					last[i] = vec.back()[i << 1];
				}
				else {
					last_index[i] = (1 << i) + 1;
					last[i] = vec.back()[(i << 1) + 1];
				}
			}
			vec.emplace_back(std::move(last));
			min_index.emplace_back(std::move(last_index));
		}
	}
	MinSegmentTree(const int size) : MinSegmentTree(std::vector<int>(size, INT_MAX)) {};
	int get(int from, int to) const {
		int min{ INT_MAX };
		for (const auto &v: vec) {
			if ((from & 1) == 1) {
				min = std::min(min, v[from++]);
			}
			if ((to & 1) == 0) {
				min = std::min(min, v[to--]);
			}
			if (from > to) return min;
			from >>= 1;
			to >>= 1;
		}
		return min;
	}
	IndexedValue<int> getWithIndex(int from, int to) const {
		int min{ INT_MAX }, min_idx{ -1 };
		for (auto i = 0; i < vec.size(); ++i) {
			if ((from & 1) == 1) {
				if (min > vec[i][from]) {
					min = vec[i][from];
					min_idx = min_index[i][from];
				}
				else if (min == vec[i][from]) {
					min_idx = std::min(min_idx, min_index[i][from]);
				}
				++from;
			}
			if ((to & 1) == 0) {
				if (min > vec[i][to]) {
					min = vec[i][to];
					min_idx = min_index[i][to];
				}
				else if (min == vec[i][to]) {
					min_idx = std::min(min_idx, min_index[i][to]);
				}
				--to;
			}
			if (from > to) break;
			from >>= 1;
			to >>= 1;
		}
		return IndexedValue<int>{min_idx, min};
	}
	void update(int position, const int new_value) {
		vec[0][position] = new_value;
		position >>= 1;
		for (auto i = 1; i < vec.size(); ++i) {
			if (vec[i].size() <= position) return;
			if (vec[i - 1][position << 1] <= vec[i - 1][(position << 1) + 1]) {
				vec[i][position] = vec[i - 1][position << 1];
				min_index[i][position] = min_index[i - 1][position << 1];
			}
			else {
				vec[i][position] = vec[i - 1][(position << 1) + 1];
				min_index[i][position] = min_index[i - 1][(position << 1) + 1];
			}
			if (vec[i][position] < new_value) return;
			position >>= 1;
		}
	}
};
class SumSegmentTree {
	std::vector<std::vector<int>> vec;
public:
	SumSegmentTree(const std::vector<int>& initial_state) : vec{ initial_state } {
		while (vec.back().size() > 1) {
			std::vector<int> last(vec.back().size() >> 1);
			for (auto i = 0; i < last.size(); ++i) {
				last[i] = vec.back()[i << 1] + vec.back()[(i << 1) + 1];
			}
			vec.emplace_back(std::move(last));
		}
	}
	SumSegmentTree(const int size) : SumSegmentTree(std::vector<int>(size, 0)) {};
	int get(int from, int to) const {
		int sum{ 0 };
		for (const auto &v: vec) {
			if ((from & 1) == 1) {
				sum += v[from++];
			}
			if ((to & 1) == 0) {
				sum += v[to--];
			}
			if (from > to) break;
			from >>= 1;
			to >>= 1;
		}
		return sum;
	}
	void update(int position, const int new_value) {
		vec[0][position] = new_value;
		position >>= 1;
		for (auto i = 1; i < vec.size(); ++i) {
			if (vec[i].size() <= position) return;
			vec[i][position] = vec[i - 1][position << 1] + vec[i - 1][(position << 1) + 1];
			position >>= 1;
		}
	}
};
struct Query {
	int from, to, rank;
};
struct Range {
	int from, to;
};
int main() {
	int n, q; std::cin >> n >> q;
	std::vector<int> value(n);
	for (auto& v : value) std::cin >> v;
	std::vector<std::vector<int>> nodes(n);
	for (auto i = 1; i < n; ++i) {
		int a, b; std::cin >> a >> b; --a; --b;
		nodes[a].push_back(b);
		nodes[b].push_back(a);
	}
	std::vector<int> depth(n, -1), in_position(n), out_position(n), euler_tour; euler_tour.reserve(n << 1);
	std::stack<int> stack; depth[0] = 0; stack.push(0);
	while (!stack.empty()) {
		const auto top = stack.top(); stack.pop();
		if (top >= 0) {
			stack.push(-1 - top);
			const auto current = top;
			in_position[current] = euler_tour.size();
			euler_tour.push_back(current);
			for (const auto next : nodes[current]) if (depth[next] == -1) {
				depth[next] = depth[current] + 1;
				stack.push(-1 - top);
				stack.push(next);
			}
		}
		else {
			const auto current = -1 - top;
			out_position[current] = euler_tour.size();
			euler_tour.push_back(current);
		}
	}
	MinSegmentTree min_seg(euler_tour.size());
	for (auto i = 0; i < euler_tour.size(); ++i) {
		min_seg.update(i, depth[euler_tour[i]]);
	}

	std::vector<Query> queries(q);
	for (auto& q : queries) {
		std::cin >> q.from >> q.to >> q.rank;
		--q.from; --q.to;
	}
	std::vector<int> indices(n); std::iota(indices.begin(), indices.end(), 0);
	std::sort(indices.begin(), indices.end(), [&value](const int i, const int j) {return value[i] < value[j]; });
	std::vector<Range> searching(q, Range{ 0, n - 1 });
	const auto comparator = [](const std::pair<int, int>& a, const std::pair<int, int>& b) {return a.first > b.first; };
	std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::function<bool(const std::pair<int, int> &, const std::pair<int, int>&)>> queue(comparator), next_queue(comparator);
	for (auto i = 0; i < q; ++i) {
		queue.emplace((n - 1) >> 1, i);
	}
	while (!queue.empty()) {
		SumSegmentTree sum_seg(euler_tour.size());
		for (auto i = 0; i < indices.size(); ++i) {
			while (i + 1 < indices.size() && value[indices[i]] == value[indices[i + 1]]) {
				const auto add = indices[i++];
				sum_seg.update(in_position[add], 1);
				sum_seg.update(out_position[add], -1);
			}
			sum_seg.update(in_position[indices[i]], 1);
			sum_seg.update(out_position[indices[i]], -1);
			while (!queue.empty() && queue.top().first <= i) {
				const auto pair = queue.top(); queue.pop();
				const auto j = pair.second;
				const auto query = queries[j];
				const auto left = std::min(in_position[query.from], in_position[query.to]);
				const auto right = std::max(in_position[query.from], in_position[query.to]);
				const auto lca = in_position[euler_tour[min_seg.getWithIndex(left, right).index]];
				const auto lca_to_right = sum_seg.get(lca, right);
				const auto lca_to_left = (lca == left) ? 0 : sum_seg.get(lca + 1, left);
				const auto count = lca_to_right + lca_to_left;
				if (count < query.rank) {
					searching[j].from = pair.first + 1;
				}
				else {
					searching[j].to = pair.first;
				}
				if (searching[j].from < searching[j].to)
					next_queue.emplace((searching[j].from + searching[j].to) >> 1, j);
			}
		}
		std::swap(queue, next_queue);
	}
	for (auto i = 0; i < queries.size(); ++i) {
		std::cout << value[indices[searching[i].from]] << '\n';
	}
}



Measured memory_bytes: 24464