/*线段树染色,经典题,在这道题中学到了,只改变段,而没有下放到点,当下一次的
改变,须向下进行是,则要将父节点的颜色下方到子节点
vis[]用来标记 ,避免重复计算
*/
#include<stdio.h>
#include<string.h>
#define N 100010
struct node
{
int b;
int e;
int c;
}p[N*4];
int sum,vis[N];
void build(int x,int l,int r)
{
p[x].c=1;
p[x].b=l;
p[x].e=r;
p[x].num=1;
if(l==r)return ;
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
}
void change(int x,int l,int r,int color)
{
if(p[x].c==color)return ;
if(p[x].b==l&&p[x].e==r)
{
p[x].c=color;//只改变段
return ;
}
if(p[x].c>=1)
{
p[x*2].c=p[x].c;//下放到子节点
p[x*2+1].c=p[x].c;
p[x].c=-1;
}
int mid=(p[x].b+p[x].e)/2;
if(r<=mid)change(x*2,l,r,color);
else
{
if(l>mid)change(x*2+1,l,r,color);
else
{
change(x*2,l,mid,color);
change(x*2+1,mid+1,r,color);
}
}
}
int Get(int x,int b,int e)
{
if(p[x].c>=1)
{
if(!vis[p[x].c]){vis[p[x].c]=1;return 1;}
else
return 0;
}
int mid=(p[x].b+p[x].e)/2;
if(e<=mid)
{
return Get(x*2,b,e);
}
else
{
if(b>mid)return Get(x*2+1,b,e);
else
{
int n=Get(x*2,b,mid);
int m=Get(x*2+1,mid+1,e);
return m+n;
}
}
}
int main()
{
int T;
int L,O;
while(scanf("%d%d%d",&L,&T,&O)!=EOF){
build(1,1,L);
getchar();
char str[4];
int b,e,c;
sum=0;
while(O--)
{
scanf("%s",str);
if(str[0]=='C')
{
scanf("%d%d%d",&b,&e,&c);
int t;
if(b>e){t=b;b=e;e=t;}
change(1,b,e,c);
}
else
{
scanf("%d%d",&b,&e);
int t;
if(b>e){t=b;b=e;e=t;}
sum=0;
for(int i=0;i<=T;i++)vis[i]=0;
sum=Get(1,b,e);
/*for(int i=1;i<=T;i++)
{
if(vis[i])sum++;
}*/
printf("%d\n",sum);
}
}
}
}