#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;
}