#include<cstdio>
#include<bitset>
using std::bitset;
int n,x,y,m,q,op,c,temp; //op是操作数
bitset<60000> s[3*(int)(10e4)],maxm,tbit; //s是序列集,maxm是限制长度的序列,tbit是存储中间结果的
int main()
{
scanf("%d %d %d",&n,&m,&q); //输入nmq
for(int i=1;i<=n;++i)
{
scanf("%d",&c); //输入某个集合的长度
while(c--)
{
scanf("%d",&temp); //输入集合中的一个数
s[i][temp]=1; //记录这个数的位置
}
}
for(int i=1;i<=m;++i)
maxm[i]=1; //maxm是限制长度的序列
while(q--)
{
scanf("%d %d %d",&op,&x,&y);//输入op x y
switch(op)
{
case 1: //若op==1
s[x]<<=y; //每个数的位置向左移动y位
//bitset中 0 是最低位,向左移升高位置
s[x]&=maxm; //与maxm相与,去除maxm以上的位
break; //退出switch语句
case 2: //若op==2
s[x]>>=y; //每个数的位置向右移动y位
//bitset中 0 是最低位,向右移降低位置,溢出的位会舍去
s[x]&=maxm; //与maxm相与,去除maxm以上的位
break; //退出switch语句
case 3: //若op==3
tbit=s[x]&s[y]; //求Sx和Sy的交集(与运算)
tbit&=maxm; //与maxm相与,去除maxm以上的位
printf("%lu\n",tbit.count()); //输出交集中 1 的个数
break; //退出switch语句
case 4: //若op==4
tbit=s[x]|s[y]; //求Sx和Sy的并集(或运算)
tbit&=maxm; //与maxm相与,去除maxm以上的位
printf("%lu\n",tbit.count()); //输出并集中 1 的个数
break; //退出switch语句
case 5:
tbit=s[x]^s[y]; //求Sx和Sy的对称差(异或运算)
tbit&=maxm; //与maxm相与,去除maxm以上的位
printf("%lu\n",tbit.count()); //输出对称差中 1 的个数
break; //退出switch语句
}
tbit=0;//初始化
}
return 0;
}