#include<iostream>
#include<stdlib.h>
using namespace std;
const int Max = 30050;
int pa[Max], num[Max], under[Max];
// num[x]用于根节点x记录集合的元素数量,集合其他元素的num[]以后不会用到。
// under[x]用于记录集合元素x与根节点元素的位置差值,由于根节点的under[]为0,
//故under[x]即为元素x以下的元素数量。
void make_set(int n) //初始化,每个节点的父节点就是自己本身
{
for(int x = 1; x <= n; x ++)
{
pa[x] = x;
num[x] = 1;
under[x] = 0;
}
}
int find_set(int x) //找最终的父节点
{
int tmp = pa[x];
if(x != pa[x]) //如果x不是最终的父节点
{
pa[x] = find_set(pa[x]); //继续向下寻找最终父节点,并将该节点指向最终父节点(并查集中的优化)
under[x] += under[tmp]; //每个元素与新根节点的位置差值更新
//上面的一句:在递归查找最终父节点的过程中,其实本来x与其直接父节点之间就差1层,x的直接父节点tmp
//下面有under[tmp]个元素,所以x下面的元素个数就是上式所示(其实x的直接父节点tmp下面的元素个数
//也是在递归查找最终父节点的过程中累计起来的)
}
return pa[x];
}
void union_set(int x, int y) //合并操作
{
x = find_set(x);
y = find_set(y);
if(x == y) return; //如果要移动的cube就在目的栈上则返回,不做移动
pa[x] = y; //否则就将目的栈栈底作为被移动的栈的父节点
under[x] += num[y]; //前根节点的差值改变
//移动后x下面的元素的个数=移动前x下面有的元素的个数+目的栈y中的总的元素的个数
//因为x所在是栈全部移到目的栈y上面
num[y] += num[x]; //目的栈元素的总个数=移动前x栈和y栈的元素个数之和
}
int main(){
int t;
make_set(30000);
scanf("%d", &t);
while(t --)
{
char order;
int x, y;
scanf("/n%c", &order); // 要学习这种输入格式,保险点
if(order == 'M')
{
scanf(" %d %d", &x, &y); // 输入格式
union_set(x, y);
}
else
{
scanf(" %d", &x);
find_set(x);
printf("%d/n", under[x]);
}
}
return 0;
}