#include <iostream>
#include <vector>
#include <numeric>
// These helpers and global variables should be placed outside the main and solve functions.
const int MAXN_SIZE = 100005;
std::vector<int> adj[MAXN_SIZE];
long long node_values_storage[MAXN_SIZE];
int tin[MAXN_SIZE], tout[MAXN_SIZE];
long long flat_values[MAXN_SIZE];
int timer;
long long bit[MAXN_SIZE];
int N_for_bit;
void bit_add(int idx, long long delta) {
for (; idx <= N_for_bit; idx += idx & -idx) {
bit[idx] += delta;
}
}
long long bit_query(int idx) {
long long sum = 0;
for (; idx > 0; idx -= idx & -idx) {
sum += bit[idx];
}
return sum;
}
long long range_sum(int l, int r) {
if (l > r) return 0;
return bit_query(r) - bit_query(l - 1);
}
void dfs(int u, int p) {
tin[u] = ++timer;
flat_values[timer] = node_values_storage[u];
for (int v : adj[u]) {
if (v != p) {
dfs(v, u);
}
}
tout[u] = timer;
}
bool is_ancestor(int u, int v) {
return tin[u] <= tin[v] && tout[u] >= tout[v];
}
// Paste the implementation logic into the provided solve function.
std::vector<long long> solve(int N, std::vector<int>& A, std::vector<std::vector<int>>& edges, int Q, std::vector<std::vector<int>>& query) {
N_for_bit = N;
for (int i = 1; i <= N; ++i) {
adj[i].clear();
bit[i] = 0;
node_values_storage[i] = A[i - 1];
}
for (const auto& edge : edges) {
adj[edge[0]].push_back(edge[1]);
adj[edge[1]].push_back(edge[0]);
}
timer = 0;
// Assuming the root is always 1 as is common in these problems.
dfs(1, 0);
for (int i = 1; i <= N; ++i) {
bit_add(i, flat_values[i]);
}
std::vector<long long> results;
results.reserve(Q);
for (const auto& q : query) {
int u = q[0];
int v = q[1];
int x = q[2];
// Temporarily swap values if u is not an ancestor of v
bool swapped = false;
if (!is_ancestor(u, v)) {
swapped = true;
long long val_u = node_values_storage[u];
long long val_v = node_values_storage[v];
bit_add(tin[u], val_v - val_u);
bit_add(tin[v], val_u - val_v);
}
// Calculate subtree sum for x
results.push_back(range_sum(tin[x], tout[x]));
// Revert the swap to restore original state for the next query
if (swapped) {
long long val_u = node_values_storage[u];
long long val_v = node_values_storage[v];
bit_add(tin[u], val_u - val_v);
bit_add(tin[v], val_v - val_u);
}
}
return results;
}
// This is the main function for handling I/O, as seen in your environment.
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int T;
std::cin >> T;
while (T--) {
int N;
std::cin >> N;
std::vector<int> A(N);
for (int i = 0; i < N; ++i) {
std::cin >> A[i];
}
std::vector<std::vector<int>> edges(N - 1, std::vector<int>(2));
for (int i = 0; i < N - 1; ++i) {
std::cin >> edges[i][0] >> edges[i][1];
}
int Q;
std::cin >> Q;
std::vector<std::vector<int>> query(Q, std::vector<int>(3));
for (int i = 0; i < Q; ++i) {
std::cin >> query[i][0] >> query[i][1] >> query[i][2];
}
std::vector<long long> result = solve(N, A, edges, Q, query);
for (size_t i = 0; i < result.size(); ++i) {
std::cout << result[i] << (i == result.size() - 1 ? "" : " ");
}
std::cout << "\n";
}
return 0;
}