#include<cstdio>
const int maxn=1e5+5;
int head[maxn],dep[maxn],Fa[maxn],siz[maxn];
int id[maxn],iid[maxn],top[maxn],col[maxn],cnt;
int n,m;
struct edge{
int to,nxt;
edge(int x=0,int y=0):to(x),nxt(y){}
}adj[maxn<<1];
inline void adde(int u,int v){
adj[++cnt]=edge(v,head[u]);
head[u]=cnt;
}
void dfs1(int cu,int fa){
dep[cu]=dep[fa]+1;
Fa[cu]=fa;
siz[cu]=1;
for(int i=head[cu];i;i=adj[i].nxt){
int to=adj[i].to;
if(to==fa)continue;
dfs1(to,cu);
siz[cu]+=siz[to];
}
}
void dfs2(int cu,int fir){
id[cu]=++cnt;
iid[cnt]=cu;
top[cu]=fir;
int hson=0;
for(int i=head[cu];i;i=adj[i].nxt){
int to=adj[i].to;
if(to==Fa[cu])continue;
if(siz[hson]<siz[to])
hson=to;
}
if(hson)dfs2(hson,fir);
for(int i=head[cu];i;i=adj[i].nxt){
int to=adj[i].to;
if(to==Fa[cu]||to==hson)continue;
dfs2(to,to);
}
}
struct NodeSeg{
int l,r,val,tag;
NodeSeg(int a=0,int b=0,int c=0,int d=0):
l(a),r(b),val(c),tag(d){}
void print(){
printf("%d %d %d %d\n",l,r,val,tag);
}
}seg[maxn<<2];
inline NodeSeg comb(NodeSeg a,NodeSeg b){
if(!a.l)return b;
if(!b.l)return a;
return NodeSeg(a.l,b.r,a.val+b.val-(a.r==b.l));
}
void build(int k,int l,int r){
if(l==r){
seg[k].l=seg[k].r=col[iid[l]];
seg[k].val=1;
} else {
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
seg[k]=comb(seg[k<<1],seg[k<<1|1]);
}
}
void pushdown(int k){
if(!seg[k].tag)return;
int lc=k<<1,rc=k<<1|1;
seg[rc].tag=seg[lc].tag=seg[k].tag;
seg[lc].l=seg[rc].l=seg[k].l;
seg[lc].r=seg[rc].r=seg[k].r;
seg[lc].val=seg[rc].val=1;
seg[k].tag=0;
}
void update(int k,int l,int r,int L,int R,int v){
if(R<l||r<L)return;
if(L<=l&&r<=R){
seg[k].tag=v;
seg[k].val=1;
seg[k].l=seg[k].r=v;
} else {
pushdown(k);
int mid=(l+r)>>1;
if(L<=mid) update(k<<1,l,mid,L,R,v);
if(mid<R) update(k<<1|1,mid+1,r,L,R,v);
seg[k]=comb(seg[k<<1],seg[k<<1|1]);
}
}
void modify(int u,int v,int col){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
update(1,1,n,id[top[u]],id[u],col);
u=Fa[top[u]];
} else {
update(1,1,n,id[top[v]],id[v],col);
v=Fa[top[v]];
}
}
if(id[u]>id[v]){
int t=u;
u=v, v=t;
}
update(1,1,n,id[u],id[v],col);
}
NodeSeg query(int k,int l,int r,int L,int R){
if(L<=l&&r<=R)
return seg[k];
NodeSeg res;
if(R<l||r<L)return res;
pushdown(k);
int mid=(l+r)>>1;
if(L<=mid) res=comb(res,query(k<<1,l,mid,L,R));
if(mid<R) res=comb(res,query(k<<1|1,mid+1,r,L,R));
return res;
}
int path_col(int u,int v){
NodeSeg res1,res2,res;
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
NodeSeg ans=query(1,1,n,id[top[u]],id[u]);
res1=comb(ans,res1);
u=Fa[top[u]];
} else {
NodeSeg ans=query(1,1,n,id[top[v]],id[v]);
res2=comb(ans,res2);
v=Fa[top[v]];
}
}
if(id[u]>id[v]){
int t=u;
u=v, v=t;
NodeSeg tmp=res1;
res1=res2;
res2=tmp;
}
res1=comb(res1,query(1,1,n,id[u],id[v]));
res=comb(res1,res2);
return res.val;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",col+i);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
adde(u,v); adde(v,u);
}
dfs1(1,0);
cnt=0;
dfs2(1,1);
build(1,1,n);
while(m--){
char op=getchar();
if(op=='C'){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
modify(u,v,w);
}
else if(op=='Q'){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",path_col(u,v));
}
else ++m;
}
return 0;
}