#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n;
vector<int> a, flat;
vector<vector<int>> adj;
 
struct LCA
{
    vector<vector<int>> par;
    const int lg = 18;
    vector<int> dist; // distance from the root
    vector<int> in, out;
    int t = 0;
    LCA(int n)
    {
        in = out = dist = vector<int>(n + 4);
        par = vector<vector<int>>(n + 4, vector<int>(lg + 5));
        dist[1] = 0;
        dfs(1, 1);
        pre(n);
    }
    void dfs(int i, int p)
    {
        dist[i] = dist[p] + (i != 1);
        flat.push_back(i);
        in[i] = t++;
        par[i][0] = p;
        for (auto j : adj[i])
        {
            if (j != p)
                dfs(j, i);
        }
        flat.push_back(i);
        out[i] = t++;
    }
    bool isparent(int v, int p)
    { // is p parent of v
        return in[p] <= in[v] and out[p] >= out[v];
    }
    void pre(int n)
    {
        for (int i = 1; i < lg; i++)
        {
            for (int f = 1; f <= n; f++)
            {
                par[f][i] = par[par[f][i - 1]][i - 1];
            }
        }
    }
 
    int lca(int a, int b)
    {
        if (isparent(a, b))
            return b;
        if (isparent(b, a))
            return a;
        int ret = a;
        for (int i = lg - 1; ~i; i--)
        {
            if (!isparent(b, par[ret][i]))
                ret = par[ret][i];
        }
        return par[ret][0];
    }
    int getdist(int u, int p)
    { // how many nodes are there int path from u to p
        return dist[u] - dist[p] + 1;
    }
};
vector<int> in, out;
 
struct Node
{
    int frq[31]{};
};
 
struct Segtree
{
    vector<Node> tree;
    Node neutral = Node();
    Segtree(int n, vector<int> &v)
    {
        int sz = 1;
        while (sz <= n)
        {
            sz *= 2;
        }
        tree.resize(sz * 2);
        build(1, 0, n - 1, v);
    }
    Node Single(int data)
    {
        Node ret;
        int g = abs(data);
        for (int i = 0; i < 31; i++)
        {
            ret.frq[i] = (data < 0 ? -1 : 1) * ((g & (1ll << i)) > 0);
        }
        return ret;
    }
    Node Merge(Node a, Node b)
    {
        Node ret;
        for (int i = 0; i < 31; i++)
        {
            ret.frq[i] = a.frq[i] + b.frq[i];
        }
        return ret;
    }
    void build(int x, int lx, int rx, const vector<int> &v)
    {
        if (lx == rx)
            return tree[x] = Single(v[lx]), void();
        int m = (lx + rx) >> 1;
        build(x * 2, lx, m, v);
        build(x * 2 + 1, m + 1, rx, v);
        tree[x] = Merge(tree[x * 2], tree[x * 2 + 1]);
    }
    void change(int x, int lx, int rx, const int &i, const int &val)
    {
        if (lx == rx)
            return tree[x] = Single(val), void();
        int m = (lx + rx) >> 1;
        if (i <= m)
            change(x * 2, lx, m, i, val);
        else
            change(x * 2 + 1, m + 1, rx, i, val);
        tree[x] = Merge(tree[x * 2], tree[x * 2 + 1]);
    }
    Node query(int x, int lx, int rx, const int &l, const int &r)
    {
        if (lx > r or rx < l)
            return neutral;
        if (lx >= l and rx <= r)
            return tree[x];
        int m = (lx + rx) >> 1;
        return Merge(query(x * 2, lx, m, l, r), query(x * 2 + 1, m + 1, rx, l, r));
    }
};
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    a = vector<int>(n + 4);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    adj = vector<vector<int>>(n + 4);
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    LCA lca(n);
    in = lca.in;
    out = lca.out;
    vector<int> tmp(flat.size());
    bool vis[n + 4]{};
    for (int i = 0; i < flat.size(); i++)
    {
        tmp[i] = ((vis[flat[i]] ? -a[flat[i]] : a[flat[i]]));
        vis[flat[i]] = true;
    }
    Segtree tree(flat.size(), tmp);
    int q;
    cin >> q;
    while (q--)
    {
        int op;
        cin >> op;
        if (op == 1)
        {
            int u, v;
            cin >> u >> v;
            int lc = lca.lca(u, v);
            auto resu = tree.query(1, 0, flat.size() - 1, in[lc], in[u]).frq;
            auto resv = tree.query(1, 0, flat.size() - 1, in[lc], in[v]).frq;
            int tot = lca.getdist(u, lc) + lca.getdist(v, lc) - 1;
            ll ans = 0;
            for (int i = 0; i < 31; i++)
            {
                if (resu[i] + resv[i] - ((a[lc] & (1ll << i)) > 0) == tot)
                    ans += (1ll << i);
            }
            cout << ans << '\n';
        }
        else
        {
            int u, x;
            cin >> u >> x;
            a[u] = x;
            tree.change(1, 0, flat.size() - 1, in[u], x);
            tree.change(1, 0, flat.size() - 1, out[u], -x);
        }
    }
}
