#include "bits/stdc++.h"
using namespace std;
#define int long long int
#define endl '\n'
const int maxn = 1E5 + 5;
const int logn = 19;
int tnode;
int tquery;
vector<vector<int>> graph;
vector<vector<int>> Tree;
int arr[maxn];
int subtreeSize[maxn];
int depth[maxn];
int father[maxn][logn];
int nxt[maxn];
int in[maxn];
int out[maxn];
int tym;
void makeTree(int u = 1, int p = 0) {
for (int v : graph[u]) {
if (v == p) {
continue;
}
Tree[u].push_back(v);
makeTree(v, u);
}
}
void dfsSize(int u = 1) {
subtreeSize[u] = 1;
for (int &v : Tree[u]) {
dfsSize(v);
subtreeSize[u] += subtreeSize[v];
if (subtreeSize[v] > subtreeSize[ Tree[u][0] ]) {
swap(v, Tree[u][0]);
}
}
}
void dfs(int u = 1, int lvl = 1) {
depth[u] = lvl;
for (int i = 1; i < logn; i++) {
father[u][i] = father[ father[u][i - 1] ][i - 1];
}
for (int v : Tree[u]) {
father[v][0] = u;
dfs(v, lvl + 1);
}
}
void hld(int u = 1) {
in[u] = ++tym;
for (int v : Tree[u]) {
nxt[v] = v == Tree[u][0] ? nxt[u] : v;
hld(v);
}
out[u] = tym;
}
int findLca(int u, int v) {
if (depth[u] < depth[v]) {
swap(u, v);
}
for (int i = logn - 1; i >= 0; i--) {
if (depth[ father[u][i] ] >= depth[v]) {
u = father[u][i];
}
}
if (u == v) {
return u;
}
for (int i = logn - 1; i >= 0; i--) {
if (father[u][i] != father[v][i]) {
u = father[u][i];
v = father[v][i];
}
}
return father[u][0];
}
#define lchild node * 2
#define rchild node * 2 + 1
#define mid (a + b) / 2
int STree[maxn * 4];
void update(int node, int a, int b, int pos, int val) {
if (a > b or a > pos or b < pos) {
return;
}
if (a >= pos and b <= pos) {
STree[node] = val;
return;
}
update(lchild, a, mid, pos, val);
update(rchild, mid + 1, b, pos, val);
STree[node] = STree[lchild] ^ STree[rchild];
}
int query(int node, int a, int b, int i, int j) {
if (a > b or a > j or b < i) {
return 0;
}
if (a >= i and b <= j) {
return STree[node];
}
int p = query(lchild, a, mid, i, j);
int q = query(rchild, mid + 1, b, i, j);
return p ^ q;
}
int queryUp(int u, int v) {
// v = lca
int xorsum = 0;
int L = in[v];
while (true) {
int l = in[ nxt[u] ];
int r = in[u];
if (l <= L) {
l = max(l, L);
xorsum ^= query(1, 1, tnode, l, r);
break;
}
xorsum ^= query(1, 1, tnode, l, r);
u = father[ nxt[u] ][0];
}
return xorsum;
}
int queryHld(int u, int v) {
int lca = findLca(u, v);
int lft = queryUp(u, lca);
int rgt = queryUp(v, lca);
int middle = queryUp(lca, lca);
return lft ^ rgt ^ middle;
}
void updateHld(int u, int val) {
arr[u] = val;
update(1, 1, tnode, in[u], val);
}
void init() {
graph.clear(); graph.resize(maxn);
Tree.clear(); Tree.resize(maxn);
tym = 0;
for (int i = 0; i < maxn; i++) {
subtreeSize[i] = 0;
in[i] = 0;
out[i] = 0;
nxt[i] = 0;
memset(father, 0, sizeof father[i]);
depth[i] = 0;
}
memset(STree, 0, sizeof STree);
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout.precision(12);
bool FILEIO = 1;
if (FILEIO and fopen("in.txt", "r")) {
freopen("in.txt", "r", stdin);
}
int tc;
cin >> tc;
while (tc--) {
init();
cin >> tnode;
for (int i = 1; i <= tnode; i++) {
cin >> arr[i];
}
for (int e = 1; e < tnode; e++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
makeTree();
dfsSize();
dfs();
nxt[1] = 1;
hld();
for (int i = 1; i <= tnode; i++) {
updateHld(i, arr[i]);
}
cin >> tquery;
while (tquery--) {
int type;
cin >> type;
if (type == 1) {
int u, val;
cin >> u >> val;
updateHld(u, val);
} else {
int u, v;
cin >> u >> v;
int xorsum = queryHld(u, v);
cerr << xorsum << " ";
cout << (xorsum ? "Alice" : "Bob") << endl;
}
}
}
}