#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target("avx2")
using namespace std;
using ll = long long;
using ull=unsigned long long;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
using pii = pair<int, int>;
using vi = vector<int>;
#define fi first
#define se second
#define pb push_back
const int L=64;
using row=bitset<L>;
using matr=array<row,L+1>;
consteval matr UNIT() {
matr res = {};
for (int i = 0; i < L; i++)
res[i].set(i);
return res;
}
matr mul(const matr& l,const matr& r) {
matr R = {};
for (int i = 0; i < L; i++)
for (int j = 0; j < L; j++)
R[i][j] = r[j][i];
matr res = {};
for (int i = 0; i <= L; i++)
for (int j = 0; j < L; j++)
res[i][j] = (l[i] & R[j]).count() & 1;
res[L] ^= r[L];
return res;
}
void print(matr m) {
for (int i = 0; i <= L; i++) {
for (int j = 0; j < L; j++)
cout << m[i][j];
cout << (i == L) << "\n";
}
cout << "\n";
}
matr read() {
matr res = {};
int m;
cin >> m;
while (m--) {
int s, o;
ull a;
cin >> s >> o >> a;
for (int i = 0; i < L; i++) {
int j = (i + s) % L;
if (o == 0) {
if ((a >> j) & 1)
res[L][j].flip();
else
res[i][j].flip();
} else {
if ((a >> j) & 1)
res[i][j].flip();
}
}
}
ull b;
cin >> b;
for (int i = 0; i < L; i++)
if ((b >> i) & 1)
res[L][i].flip();
// print(res);
return res;
}
struct Tree {
typedef matr T;
static constexpr matr unit = UNIT();
T f(const T &a, const T &b) { return mul(a, b); } // (any associative fn)
vector<T> s;
int n;
Tree(int n = 0, T def = unit) : s(2 * n, def), n(n) {}
void update(int pos, const T &val) {
for (s[pos += n] = val; pos /= 2;)
s[pos] = f(s[pos * 2], s[pos * 2 + 1]);
}
T query(int b, int e) { // query [b, e)
T ra = unit, rb = unit;
for (b += n, e += n; b < e; b /= 2, e /= 2) {
if (b % 2) ra = f(ra, s[b++]);
if (e % 2) rb = f(s[--e], rb);
}
return f(ra, rb);
}
};
signed main() {
cin.tie(0)->sync_with_stdio(0);
cin.exceptions(cin.failbit);
int n, q, c;
cin >> n >> q >> c;
Tree tree(n);
for (int i = 0; i < n; i++)
tree.update(i, read());
while (q--) {
int op;
cin >> op;
if (op == 0) {
int l, r;
ull x;
cin >> l >> r >> x;
matr m = tree.query(l - 1, r);
// print(m);
ull res = 0;
for (int i = 0; i < L; i++)
for (int j = 0; j < L; j++)
if (m[i][j] && ((x >> i) & 1))
res ^= 1ULL << j;
for (int j = 0; j < L; j++)
if (m[L][j])
res ^= 1ULL << j;
cout << res << "\n";
} else {
int l;
cin >> l;
tree.update(l - 1, read());
}
}
}