Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
void setIO(string a){freopen((a+".in").c_str(),"r",stdin);}
#define maxn 100009
#define ll long long
int n,q;
struct LCT{
int ch[maxn][2],f[maxn],siz[maxn],sta[maxn],son[maxn],tag[maxn];
int lson(int x){ return ch[x][0]; }
int rson(int x){ return ch[x][1]; }
int get(int x){ return ch[f[x]][1]==x;}
int isRoot(int x){ return !(ch[f[x]][0]==x||ch[f[x]][1]==x); }
void mark(int x){ if(!x)return; swap(ch[x][0],ch[x][1]),tag[x]^=1; }
void pushdown(int x){ if(tag[x]) mark(lson(x)),mark(rson(x)),tag[x]=0; }
void pushup(int x){ if(!x) return; siz[x]=siz[lson(x)]+siz[rson(x)]+son[x]+1; }
void rotate(int x){
int old=f[x],fold=f[old],which=get(x);
if(!isRoot(old)) ch[fold][ch[fold][1]==old]=x;
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
pushup(old),pushup(x);
}
void splay(int x){
int v=0,u=x;
sta[++v]=u;
while(!isRoot(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
}
void Access(int x){for(int y=0;x;y=x,x=f[x]) splay(x),son[x]=son[x]+siz[ch[x][1]]-siz[y], ch[x][1]=y, pushup(x); }
void makeRoot(int x){ Access(x), splay(x), mark(x);}
void link(int a,int b){ makeRoot(a), makeRoot(b), son[a]+=siz[b], f[b]=a, pushup(a); }
ll query(int a,int b){
makeRoot(a),makeRoot(b);
return (long long)siz[a]*(siz[b]-siz[a]);
}
}tree;
int main(){
//setIO("input");
int a,b;
char opt[5];
scanf("%d%d",&n,&q);
while(q--){
scanf("%s%d%d",opt,&a,&b);
switch(opt[0]){
case 'A': {
tree.link(a,b);
break;
}
case 'Q': {
printf("%lld\n",tree.query(a,b));
break;
}
}
}
return 0;
}