#include <bits/stdc++.h>
#define ll long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define MASK(i) (1LL << (i))
#define BIT(x, i) (((x) >> (i)) & 1)
#define creby_ThienNhan return 0;
#define TKimorz ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
const int LimN=2e5+5;
const int N=1e5+5;
const int M=1e3+5;
const int BASE=256;
const int mod=1e9+7;
char d4c[4]={'R','D','L','U'};
ll d4x[4]={0,1,0,-1};
ll d4y[4]={1,0,-1,0};
ll d4x_tuong[4]={-2,-2,2,2};
ll d4y_tuong[4]={-2,2,-2,2};
ll d8x[8]={0,1,-1,0,-1,1,1,-1};
ll d8y[8]={1,0,0,-1,-1,1,-1,1};
ll d8x_ma[8]={-1,-1,+1,+1,-2,-2,+2,+2};
ll d8y_ma[8]={-2,+2,-2,+2,-1,+1,-1,+1};
template<class X, class Y>
bool maximize(X& x, const Y y) {
    if (y > x) {x = y; return true;}
    return false;
}
template<class X, class Y>
bool minimize(X& x, const Y y) {
    if (y < x) {x = y; return true;}
    return false;
}
ll pow(ll a,ll b,ll c){
    ll tich = 1;
    a = a % c;
    for (; b > 0; b >>= 1 , a = a * a % c){
        if (b & 1) tich = tich * a % c;
      }
    return tich;
}
ll n, q, cnt;
ll a[LimN];
ll head[LimN], p[LimN], heavy[LimN], h[LimN], pos[LimN],invpos[LimN];
vector<int> adj[LimN];
struct tn{
    int cnt[10];
    int lazy;
    tn() {
        memset(cnt,0,sizeof cnt);
        lazy=0;
    }
}st[LimN * 4];
int dfs(int u, int par) {
    int cur_sz = 1, max_son_sz = 0;
    for (int v : adj[u]) {
        if (v == par) continue;
        h[v] = h[u] + 1;
        p[v] = u;
        int son_sz = dfs(v, u);
        if (son_sz > max_son_sz) {
            max_son_sz = son_sz;
            heavy[u] = v;
        }
        cur_sz += son_sz;
    }
    return cur_sz;
}

void hld(int u, int top) {
    head[u] = top;
    pos[u] = ++cnt;
    invpos[cnt]=u;
    if (heavy[u]) hld(heavy[u], top);
    for (int v : adj[u]) {
        if (v != p[u] && v != heavy[u]) {
            hld(v, v);
        }
    }
}

void down(int id, int l, int r, int mask) {
    int len=r-l+1;
    for (int i=0; i<10; i++) {
        if (BIT(mask,i)) {
            st[id].cnt[i]=len-st[id].cnt[i];
        }
    }
    st[id].lazy^=mask;
}
void push(int id, int l, int r) {
    if (st[id].lazy) {
        int mid=(l+r)/2;
        down(id*2,l,mid,st[id].lazy);
        down(id*2+1,mid+1,r,st[id].lazy);
        st[id].lazy=0;
    }
}
void build(int id, int l, int r) {
    if (l==r) {
        int val=a[invpos[l]];
        for (int i=0; i<10; i++) {
            st[id].cnt[i]= val >> i & 1;
        }
        return;
    }
    int mid=(l+r)/2;
    build(id*2,l,mid);
    build(id*2+1,mid+1,r);
    for (int i=0; i<10; i++) {
        st[id].cnt[i]=st[id*2].cnt[i] + st[id*2+1].cnt[i];
    }
}

void update(int id, int l, int r, int u, int v, int val) {
    if (r < u || v < l) return;
    if (u <= l && r <= v) {
        down(id,l,r,val);
        return;
    }
    push(id,l,r);
    int mid = (l + r) / 2;
    update(id * 2, l, mid, u, v, val);
    update(id * 2 + 1, mid + 1, r, u, v, val);
    for (int i=0; i<10; i++) {
        st[id].cnt[i]=st[id*2].cnt[i] + st[id*2+1].cnt[i];
    }
}

ll get(int id, int l, int r, int u, int v) {
    if (r < u || l > v) return 0;
    if (u <= l && r <= v) {
        int ans=0;
        for (int i=0; i<10; i++) {
            ans+=st[id].cnt[i] * MASK(i);
        }
        return ans;
    }
    push(id,l,r);
    int mid = l + r >> 1;
    return get(id * 2, l, mid, u, v) + get(id * 2 + 1, mid + 1, r, u, v);
}

void update_path(int x, int y, int val) {
    while (head[x] != head[y]) {
        if (h[head[x]] < h[head[y]]) swap(x, y);
        update(1, 1, n, pos[head[x]], pos[x], val);
        x = p[head[x]];
    }
    if (h[x] > h[y]) swap(x, y);
    update(1, 1, n, pos[x], pos[y], val);
}

ll query(int x, int y) {
    ll res = 0;
    while (head[x] != head[y]) {
        if (h[head[x]] < h[head[y]]) swap(x, y);
        res += get(1, 1, n, pos[head[x]], pos[x]);
        x = p[head[x]];
    }
    if (h[x] > h[y]) swap(x, y);
    res += get(1, 1, n, pos[x], pos[y]);
    return res;
}


void solve() {
    int sub;
    cin >> sub;
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i < n; ++i) {
        int u, v; cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    hld(1, 1);
    build(1,1,n);
    cin >> q;
    while (q--) {
        int type; cin >> type;
        if (type == 1) {
            int x, y, v;
            cin >> x >> y >> v;
            update_path(x, y, v);
        } else {
            int x, y;
            cin >> x >> y;
            cout << query(x, y) << endl;
        }
    }
}

int main() {
    TKimorz
    ll t=1;
    while (t--) {
        solve();
    }
    creby_ThienNhan
}
