#include<iostream>
#include<cstring>
using namespace std;
struct Hash
{
unsigned long long x,h[64];
};
inline unsigned long long operator *
(unsigned long long x,const Hash &h)
{
unsigned long long ret=h.x;
for(int i=0;i<64;i++)
{
if(__builtin_popcountll(x&h.h[i])&1)
{
ret^=1ull<<i;
}
}
return ret;
}
inline Hash operator *
(const Hash &a,const Hash &b)
{
static Hash ret;
memset(ret.h,0,sizeof(ret.h)),ret.x=b.x;
for(int i=0;i<64;i++)
{
for(int j=0;j<64;j++)
{
if(b.h[i]&(1ull<<j))
{
ret.h[i]^=a.h[j];
ret.x^=((a.x>>j)&1)<<i;
}
}
}
return ret;
}
Hash a[80000];
inline void update(int p)
{
a[p]=a[p<<1]*a[(p<<1)|1];
}
inline void change(int l,int r,int x,const Hash &v,int p)
{
if(l==r)
{
a[p]=v;
return;
}
int mid=l+r>>1;
x<=mid?change(l,mid,x,v,p<<1)
:change(mid+1,r,x,v,(p<<1)|1);
update(p);
}
void query(int l,int r,int ll,int rr,unsigned long long &x,int p)
{
if(r<ll||l>rr)
{
return;
}
if(ll<=l&&r<=rr)
{
x=x*a[p];
return;
}
int mid=l+r>>1;
query(l,mid,ll,rr,x,p<<1);
query(mid+1,r,ll,rr,x,(p<<1)|1);
}
inline Hash get()
{
static Hash ret;
memset(&ret,0,sizeof(ret));
int m;
cin>>m;
while(m--)
{
int s;
bool op;
unsigned long long v;
cin>>s>>op>>v;
for(int i=0;i<64;i++)
{
if(op==((v>>i)&1))
{
ret.h[i]^=1ull<<(i+64-s&63);
}
else if(!op)
{
ret.x^=1ull<<i;
}
}
}
unsigned long long x;
cin>>x;
ret.x^=x;
return ret;
}
int n,q,c;
Hash A[20010];
void build(int l,int r,int p)
{
if(l==r)
{
a[p]=A[l];
return;
}
int mid=l+r>>1;
build(l,mid,p<<1);
build(mid+1,r,(p<<1)|1);
update(p);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>q>>c;
for(int i=1;i<=n;i++)
{
A[i]=get();
}
build(1,n,1);
while(q--)
{
bool op;
cin>>op;
if(op)
{
int x;
cin>>x;
change(1,n,x,get(),1);
}
else
{
int l,r;
unsigned long long x;
cin>>l>>r>>x;
query(1,n,l,r,x,1);
cout<<x<<'\n';
}
}
return 0;
}