#include<cstdio>
#include<iostream>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int n,m,cnt,tt,x0,y0,x1,y1;
struct segtree{
int l,r;
int a_to_a,a_to_b,b_to_a,b_to_b;
int mxl1,mxl2,mxr1,mxr2;
}tree[2000010];
struct edge{
int to,next;
}e[500010];
int head[200010];
segtree query;
bool mrk[200010],mrkl[200010],mrkr[200010];
int fa[200010][20],depth[200010],son[200010];
int chain[200010],belong[200010],place[200010],pplace[200010];
inline int max(int a,int b,int c)
{
if (b>a)a=b;
if (c>a)a=c;
return a;
}
inline int max(int a,int b,int c,int d,int e,int f)
{
if (b>a)a=b;
if (c>a)a=c;
if (d>a)a=d;
if (e>a)a=e;
if (f>a)a=f;
return a;
}
inline void ins(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
inline void insert(int u,int v)
{
ins(u,v);
ins(v,u);
}
inline void dfs1(int x,int dep)
{
if (mrk[x])return;mrk[x]=1;
son[x]=1;depth[x]=dep;
for (int i=1;i<20;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=head[x];i;i=e[i].next)
if (!mrk[e[i].to])
{
fa[e[i].to][0]=x;
dfs1(e[i].to,dep+1);
son[x]+=son[e[i].to];
}
}
inline void dfs2(int x,int chain)
{
place[x]=++tt;pplace[tt]=x;
belong[x]=chain;
int mx=-1,res=-1;
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa[x][0])
{
if (son[e[i].to]>mx)
{
mx=son[e[i].to];
res=e[i].to;
}
}
if (res==-1)return;
dfs2(res,chain);
for (int i=head[x];i;i=e[i].next)
if (res!=e[i].to&&fa[x][0]!=e[i].to)
dfs2(e[i].to,e[i].to);
}
inline int LCA(int x,int y)
{
if (depth[x]<depth[y])swap(x,y);
int res=depth[x]-depth[y];
for (int i=0;i<20;i++)
if (res & (1<<i))x=fa[x][i];
for (int i=19;i>=0;i--)
if (fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
if (x==y)return x;
return fa[x][0];
}
inline void ref(int a,int b,int &c)
{
if (a!=-1&&b!=-1)c=max(c,a+b);
}
segtree merge(segtree a,segtree b)
{
if (a.l==0)return b;
if (b.l==0)return a;
segtree k;
k.a_to_a=k.a_to_b=k.b_to_a=k.b_to_b=-1;
k.mxl1=a.mxl1;
k.mxl2=a.mxl2;
k.mxr1=b.mxr1;
k.mxr2=b.mxr2;
k.l=min(a.l,b.l); k.r=max(a.r,b.r);
ref(a.a_to_a,b.a_to_a,k.a_to_a);
ref(a.a_to_b,b.b_to_a,k.a_to_a);
ref(a.a_to_a,b.a_to_b,k.a_to_b);
ref(a.a_to_b,b.b_to_b,k.a_to_b);
ref(a.b_to_a,b.a_to_a,k.b_to_a);
ref(a.b_to_b,b.b_to_a,k.b_to_a);
ref(a.b_to_a,b.a_to_b,k.b_to_b);
ref(a.b_to_b,b.b_to_b,k.b_to_b);
ref(a.a_to_a,b.mxl1,k.mxl1);
ref(a.a_to_b,b.mxl2,k.mxl1);
ref(a.b_to_a,b.mxl1,k.mxl2);
ref(a.b_to_b,b.mxl2,k.mxl2);
ref(a.mxr1,b.a_to_a,k.mxr1);
ref(a.mxr1,b.a_to_b,k.mxr2);
ref(a.mxr2,b.b_to_a,k.mxr1);
ref(a.mxr2,b.b_to_b,k.mxr2);
return k;
}
inline void buildtree(int now,int l,int r)
{
tree[now].l=l;tree[now].r=r;
if (l==r)
{
tree[now].a_to_a=tree[now].a_to_b=tree[now].b_to_a=tree[now].b_to_b=-1;
tree[now].mxl1=tree[now].mxl2=tree[now].mxr1=tree[now].mxr2=-1;
if (mrkl[pplace[l]])tree[now].a_to_a=1,tree[now].mxl1=tree[now].mxr1=1;
if (mrkr[pplace[l]])tree[now].b_to_b=1,tree[now].mxl2=tree[now].mxr2=1;
if (mrkl[pplace[l]]&&mrkr[pplace[l]])
{
tree[now].a_to_b=2;
tree[now].b_to_a=2;
tree[now].mxl1=tree[now].mxl2=2;
tree[now].mxr1=tree[now].mxr2=2;
}
return;
}
int mid=(l+r)>>1;
buildtree(now<<1,l,mid);
buildtree(now<<1|1,mid+1,r);
tree[now]=merge(tree[now<<1],tree[now<<1|1]);
}
inline segtree ask_in_tree(int now,int x,int y)
{
int l=tree[now].l,r=tree[now].r;
if (l==x&&r==y)return tree[now];
int mid=(l+r)>>1;
if (y<=mid)return ask_in_tree(now<<1,x,y);
else if (x>mid)return ask_in_tree(now<<1|1,x,y);
else return merge(ask_in_tree(now<<1,x,mid),ask_in_tree(now<<1|1,mid+1,y));
}
inline segtree ask(int from,int to,bool flag)
{
int l,r;
segtree s;s.l=s.r=0;
while (belong[from]!=belong[to])
{
l=place[belong[from]];
r=place[from];
s=merge(ask_in_tree(1,l,r),s);
from=fa[belong[from]][0];
}
l=place[to];
r=place[from];
if (flag)
{
if (place[to]+1<=place[from])s=merge(ask_in_tree(1,l+1,r),s);
}else s=merge(ask_in_tree(1,l,r),s);
return s;
}
inline void cal()
{
int a=read(),b=read(),lca=LCA(a,b);
if (!mrkl[a]&&!mrkr[a]){printf("0\n");return;}
segtree q1=ask(a,lca,1);
segtree q2=ask(b,lca,0);
swap(q1.a_to_b,q1.b_to_a);
swap(q1.mxl1,q1.mxr1);
swap(q1.mxl2,q1.mxr2);
q1=merge(q1,q2);
int ans=max(q1.a_to_a,q1.a_to_b,q1.b_to_a,q1.b_to_b,q1.mxl1,q1.mxl2);
if (ans==-1)ans=0;
printf("%d\n",ans);
}
inline void change_in_tree(int now,int x,bool m1,bool m2)
{
int l=tree[now].l,r=tree[now].r;
if (l==r)
{
tree[now].a_to_a=tree[now].a_to_b=tree[now].b_to_a=tree[now].b_to_b=-1;
tree[now].mxl1=tree[now].mxl2=tree[now].mxr1=tree[now].mxr2=-1;
if (m1)tree[now].a_to_a=1,tree[now].mxl1=tree[now].mxr1=1;
if (m2)tree[now].b_to_b=1,tree[now].mxl2=tree[now].mxr2=1;
if (m1&&m2)
{
tree[now].a_to_b=tree[now].b_to_a=2;
tree[now].mxl1=tree[now].mxl2=tree[now].mxr1=tree[now].mxr2=2;
}
return;
}
int mid=(l+r)>>1;
if (x<=mid)change_in_tree(now<<1,x,m1,m2);
else change_in_tree(now<<1|1,x,m1,m2);
tree[now]=merge(tree[now<<1],tree[now<<1|1]);
}
inline void wrk()
{
int a=read();
bool m1=0,m2=0;
char ch=getchar();while (ch!=‘.‘&&ch!=‘#‘)ch=getchar();
if (ch==‘.‘)mrkl[a]=m1=1;
ch=getchar();while (ch!=‘.‘&&ch!=‘#‘)ch=getchar();
if (ch==‘.‘)mrkr[a]=m2=1;
change_in_tree(1,place[a],m1,m2);
}
int main()
{
n=read();m=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read();
insert(x,y);
}
for(int i=1;i<=n;i++)
{
char ch=getchar();while (ch!=‘#‘&&ch!=‘.‘)ch=getchar();
if (ch==‘.‘)mrkl[i]=1;
ch=getchar();while (ch!=‘#‘&&ch!=‘.‘)ch=getchar();
if (ch==‘.‘)mrkr[i]=1;
}
dfs1(1,0);
dfs2(1,1);
buildtree(1,1,n);
for(int i=1;i<=m;i++)
{
char opr=getchar();
while (opr!=‘Q‘&&opr!=‘C‘)opr=getchar();
if (opr==‘Q‘)cal();
if (opr==‘C‘)wrk();
}
return 0;
}