#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define sz 1024001
#define INV 1
#define SET 2
#define RESET 3
using namespace std;
struct segment{
int pending_op_typ;
int sum;
int left,right;
int len;
};
segment tree[sz*4];
string ss;
void init(int node,int b,int e)
{
tree[node].len = e-b+1;
tree[node].left=b;
tree[node].right=e;
tree[node].pending_op_typ=0;
if(b==e)
{
if(ss[b]=='1')
tree[node].sum=1;
else
tree[node].sum=0;
return;
}
int Left = node*2;
int Right = (node<<1)|1;
int mid = (b+e)>>1;
init(Left,b,mid);
init(Right,mid+1,e);
tree[node].sum=tree[Left].sum+tree[Right].sum;
}
void change(int node,int opr)
{
if(opr==SET)
{
tree[node].sum=tree[node].len;
tree[node].pending_op_typ=opr;
}
else if(opr==RESET)
{
tree[node].sum=0;
tree[node].pending_op_typ=opr;
}
else if(opr==INV)
{
tree[node].sum=tree[node].len-tree[node].sum;
if(tree[node].pending_op_typ==SET)//inverse the operation and apply
{
tree[node].pending_op_typ=RESET;
}
else if(tree[node].pending_op_typ==RESET)//inverse the operation and apply
{
tree[node].pending_op_typ=SET;
}
else if(tree[node].pending_op_typ==INV)//inverse the operation and apply
{
tree[node].pending_op_typ=0;
}
else if(tree[node].pending_op_typ==0)//inverse the operation and apply
{
tree[node].pending_op_typ=INV;
}
}
}
void propagate(int node)
{
if(tree[node].pending_op_typ==0)
return;
int Left=2*node;
int Right=2*node+1;
change(Left,tree[node].pending_op_typ);
change(Right,tree[node].pending_op_typ);
tree[node].pending_op_typ=0;
}
int query(int node,int i,int j)
{
int b=tree[node].left;
int e=tree[node].right;
if(i>e || j<b)
return 0;
propagate(node);
if(i<=b && j>=e)
{
return tree[node].sum;
}
else
{
int Left = node<<1;
int Right = (node<<1)|1;
int p1 = query(Left,i,j);
int p2 = query(Right,i,j);
return p1+p2;
}
}
void update(int node,int i,int j,int opr)
{
int left = tree[node].left,right=tree[node].right;
propagate(node);
if(i>right || j<left)
return;
if(left>=i && right<=j)
{
change(node,opr);
return;
}
else
{
int Left = node*2;
int Right = node*2+1;
update(Left,i,j,opr);
update(Right,i,j,opr);
tree[node].sum=tree[Left].sum+tree[Right].sum;
}
}
// 0 for Barbary, 1 for Buccaneer
int main()
{
int t,tym,M,qry;
int a,b;
int kase=1,cnt;
bool flag;
string s,str;
scanf("%d",&t);
while(t--)
{
flag=0;
cnt=1;
scanf("%d",&tym);
s="";
while(tym--)
{
scanf("%d",&M);
cin>>str;
while(M--)
s.append(str);
}
ss = "2";
ss.append(s);
init(1,1,ss.size()-1);//init(1,1,ss.size()-1);
scanf("%d",&qry);
while(qry--)
{
cin>>str;
scanf("%d%d",&a,&b);
if(str=="F")
{
update(1,a+1,b+1,SET);//convert to buccaneer
}
else if(str=="E")
{
update(1,a+1,b+1,RESET);//convert to barbary =0
}
else if(str=="I")
{
update(1,a+1,b+1,INV);//inverse the pirates
}
else if(str=="S")
{
if(flag==0)
{
cout<<"Case "<<kase++<<":\n";
}
flag=1;
cout<<"Q"<<cnt++<<": ";
cout<<query(1,a+1,b+1)<<"\n";
}
}
}
return 0;
}