#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<stack>
#include<map>
#include<climits>
#include<set>
#include<iostream>
#define rint() read<int>()
#define rll() read<ll>()
using namespace std;
typedef long long ll;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
const int INF=1e9;
const ll LLINF=1e18;
template<typename T>
inline T Min(T x,T y){return x<y?x:y;}
template<typename T>
inline T Max(T x,T y){return x>y?x:y;}
template<typename T>
inline void Swap(T&x,T&y){int t=x;x=y;y=t;return;}
const int MAXN(1e5+10);
int n,m,a[MAXN];
struct E{int to,nxt;};
E edge[MAXN<<1];
int head[MAXN],tot;
inline void add_edge(int u,int v)
{
edge[++tot].nxt=head[u];
head[u]=tot;
edge[tot].to=v;
return;
}
int dfn[MAXN],rk[MAXN],cnt,par[MAXN],son[MAXN],siz[MAXN],dep[MAXN],top[MAXN];
inline void dfs1(int u,int fa)
{
par[u]=fa,siz[u]=1,dep[u]=dep[fa]+1;
for(register int i=head[u];i;i=edge[i].nxt)
{
E e=edge[i];
if(e.to==fa) continue;
dfs1(e.to,u);
siz[u]+=siz[e.to];
if(siz[e.to]>siz[son[u]]) son[u]=e.to;
}
return;
}
inline void dfs2(int u,int topf)
{
top[u]=topf;
dfn[u]=++cnt;
rk[cnt]=u;
if(son[u]) dfs2(son[u],topf);
for(register int i=head[u];i;i=edge[i].nxt)
{
E e=edge[i];
if(e.to!=son[u]&&e.to!=par[u]) dfs2(e.to,e.to);
}
return;
}
int Lc,Rc;
struct T{int sum,tag,lcol,rcol;};
T tree[MAXN*4];
inline int lc(int p){return p<<1;}
inline int rc(int p){return p<<1|1;}
inline T push_up(T ls,T rs)
{
T rt;
rt.lcol=ls.lcol,rt.rcol=rs.rcol;
rt.sum=ls.sum+rs.sum;
if(ls.rcol==rs.lcol) --rt.sum;
return rt;
}
inline void lazy_tag(int u,int k)
{
tree[u].tag=k;
tree[u].sum=1;
tree[u].lcol=k,tree[u].rcol=k;
return;
}
inline void push_down(int u,int l,int r)
{
if(!tree[u].tag) return;
int mid=(l+r)>>1;
lazy_tag(lc(u),tree[u].tag);
lazy_tag(rc(u),tree[u].tag);
tree[u].tag=0;
return;
}
inline void build(int u,int l,int r)
{
if(l==r)
{
tree[u].sum=1;
tree[u].lcol=a[rk[u]];
tree[u].rcol=a[rk[u]];
return;
}
int mid=(l+r)>>1;
build(lc(u),l,mid);
build(rc(u),mid+1,r);
tree[u]=push_up(tree[lc(u)],tree[rc(u)]);
return;
}
inline void update(int u,int l,int r,int ln,int rn,int k)
{
if(ln<=l&&r<=rn)
{
lazy_tag(u,k);
return;
}
push_down(u,l,r);
int mid=(l+r)>>1;
if(ln<=mid) update(lc(u),l,mid,ln,rn,k);
if(rn>mid) update(rc(u),mid+1,r,ln,rn,k);
tree[u]=push_up(tree[lc(u)],tree[rc(u)]);
return;
}
inline T query(int u,int l,int r,int ln,int rn)
{
T res;
res.tag=-1;
if(l==ln) Lc=tree[u].lcol;
if(r==rn) Rc=tree[u].rcol;
if(ln<=l&&r<=rn) return tree[u];
push_down(u,l,r);
int mid=(l+r)>>1;
if(ln<=mid) res=query(lc(u),l,mid,ln,rn),res.tag=1;
if(rn>mid)
{
if(res.tag==-1) res=query(rc(u),mid+1,r,ln,rn);
else res=push_up(res,query(rc(u),mid+1,r,ln,rn));
}
return res;
}
inline void modify(int x,int y,int k)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy]) Swap(fx,fy),Swap(x,y);
update(1,dfn[fx],dfn[x],dfn[fx],dfn[x],k);
x=par[fx];
fx=top[x];
}
if(dep[x]>dep[y]) Swap(x,y);
update(1,dfn[x],dfn[y],dfn[x],dfn[y],k);
return;
}
inline int qcolor(int x,int y)
{
int ans(0);
int ans1(-1),ans2(-1);
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy]) Swap(fx,fy),Swap(x,y),Swap(ans1,ans2);
ans+=query(1,dfn[fx],dfn[x],dfn[fx],dfn[x]).sum;
if(ans1==Rc) --ans;
ans1=Lc;
x=par[fx];
fx=top[x];
}
if(dep[x]>dep[y]) Swap(x,y);
ans+=query(1,dfn[x],dfn[y],dfn[x],dfn[y]).sum;
if(Rc==ans1) --ans;
if(Lc==ans2) --ans;
return ans;
}
int main()
{
n=read(),m=read();
for(register int i=1;i<=n;i++) a[i]=read();
for(register int i=1;i<n;i++)
{
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
while(m--)
{
char opt[4];
scanf("%s",opt);
int u=read(),v=read();
if(opt[0]=='C')
{
int w=read();
modify(u,v,w);
}
else printf("ans:%d\n",qcolor(u,v));
}
return 0;
}