//OOOOOOOOOOOOOOOOrz
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int num=0,sign=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
while (ch>='0'&&ch<='9') num=(num<<3)+(num<<1)+(ch^48),ch=getchar();
return num*sign;
}
const int N=1e5+7;
const int INF=1e9;
int siz[N],son[N],top[N],dep[N],fa[N],idx[N];
int n,m,cnt,a[N],b[N];
vector <int> g[N];
void dfs1(int x,int f){
fa[x]=f;
dep[x]=dep[f]+1;
siz[x]=1;
for(int i=0;i<g[x].size();i++){
int y=g[x][i];
if(y==f) continue;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int topf){
top[x]=topf;
idx[x]=++cnt;a[cnt]=b[x];
if(son[x]) dfs2(son[x],topf);
for(int i=0;i<g[x].size();i++){
int y=g[x][i];
if(!idx[y]) dfs2(y,y);
}
}
struct node{
int data,lc,rc,lazy;
node(){data=0;lc=rc=lazy=0;}
}t[N<<2];
struct SGT{
node merge(node a,node b){
node c;
c.data=a.data+b.data-(a.rc==b.lc);
c.lc=a.lc;c.rc=b.rc;
return c;
}
void build(int l,int r,int id){
if(l==r){
t[id].data=1;
t[id].lc=t[id].rc=a[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,id<<1);build(mid+1,r,id<<1|1);
t[id]=merge(t[id<<1],t[id<<1|1]);
}
void f(int id,int k){
t[id].data=1;
t[id].lc=t[id].rc=t[id].lazy=k;
}
void pushdown(int id){
if(!t[id].lazy) return ;
f(id<<1,t[id].lazy);
f(id<<1|1,t[id].lazy);
t[id].lazy=0;
}
void change(int l,int r,int id,int k,int L,int R){
if(l<=L&&R<=r){
f(id,k);
return ;
}
pushdown(id);
int mid=(L+R)>>1;
if(mid>=l) change(l,r,id<<1,k,L,mid);
if(mid<r) change(l,r,id<<1|1,k,mid+1,R);
t[id]=merge(t[id<<1],t[id<<1|1]);
}
node query(int l,int r,int id,int L,int R){
if(l<=L&&R<=r) return t[id];
pushdown(id);
int mid=(L+R)>>1;
node x,y;
if(mid>=l) x=query(l,r,id<<1,L,mid);
if(mid<r) y=query(l,r,id<<1|1,mid+1,R);
return merge(x,y);
}
void Change(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(idx[top[x]],idx[x],1,k,1,n);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(idx[x],idx[y],1,k,1,n);
}
node Query(int x,int y){
node L,R;
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]]){
R=merge(query(idx[top[y]],idx[y],1,1,n),R);
y=fa[top[y]];
}
else{
L=merge(query(idx[top[x]],idx[x],1,1,n),L);
x=fa[top[x]];
}
}
if(dep[x]>dep[y]) L=merge(query(idx[y],idx[x],1,1,n),L);
else R=merge(query(idx[x],idx[y],1,1,n),R);
swap(L.lc,L.rc);
return merge(L,R);
}
}tree;
signed main(){
n=rd();m=rd();
for(int i=1;i<=n;i++) b[i]=rd();
for(int i=1;i<n;i++){
int x=rd(),y=rd();
g[x].push_back(y);
g[y].push_back(x);
}
dfs1(1,0);dfs2(1,1);
tree.build(1,n,1);
while(m--){
char op;
cin>>op;
int x=rd(),y=rd(),z;
if(op=='C'){
z=rd();
tree.Change(x,y,z);
}
else{
printf("%d\n",tree.Query(x,y).data);
}
}
return 0;
}