#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,m,a[N];
int deep[N],size[N],hs[N],dfn[N],trk[N],fat[N],top[N],cnt;
vector<int> to[N];
struct Segment_Tree{
long long tree[N<<6],tag[N<<6],ls[N<<6],rs[N<<6];
void down(int l,int r,int pos)
{
if(tag[pos]==0||l==r)
{
if(l==r&&tag[pos]!=0)
{
a[trk[l]]=tag[pos];
}
return;
}
tree[pos*2]=tree[pos*2+1]=1;
tag[pos*2]=tag[pos*2+1]=tag[pos];
ls[pos*2]=rs[pos*2]=tag[pos*2];
ls[pos*2+1]=rs[pos*2+1]=tag[pos*2+1];
tag[pos]=0;
}
void up(int l,int r,int pos)
{
if(l==r) return;
tree[pos]=tree[pos*2]+tree[pos*2+1];
if(rs[pos*2]==ls[pos*2+1]) tree[pos]--;
ls[pos]=ls[pos*2],rs[pos]=rs[pos*2+1];
}
void build(int l,int r,int pos)
{
if(l==r)
{
tree[pos]=1;
ls[pos]=rs[pos]=a[trk[l]];
return;
}
int mid=(l+r)>>1;
build(l,mid,pos*2);
build(mid+1,r,pos*2+1);
up(l,r,pos);
}
int query(int l,int r,int ql,int qr,int pos)
{
if(ql<=l&&r<=qr) return tree[pos];
down(l,r,n);
int mid=(l+r)>>1;
int ans=0,cl=0,cr=0;
if(ql<=mid)
{
ans+=query(l,mid,ql,qr,pos*2);
cl=rs[pos*2];
}
if(qr>mid)
{
ans+=query(mid+1,r,ql,qr,pos*2+1);
cr=ls[pos*2+1];
}
up(l,r,pos);
if(cl==cr&&cl!=0&&cr!=0) ans--;
return ans;
}
void update(int l,int r,int ql,int qr,int pos,int w)
{
if(ql<=l&&r<=qr)
{
ls[pos]=rs[pos]=tag[pos]=w,tree[pos]=1;
return ;
}
down(l,r,pos);
int mid=(l+r)>>1;
if(ql<=mid) update(l,mid,ql,qr,pos*2,w);
if(qr>mid) update(mid+1,r,ql,qr,pos*2+1,w);
up(l,r,pos);
}
int find(int l,int r,int q,int pos)
{
if(l==r)
{
if(tag[pos]!=0) a[trk[l]]=tag[pos];
return a[trk[l]];
}
down(l,r,pos);
int mid=(l+r)>>1;
if(q<=mid) return find(l,mid,q,pos*2);
else return find(mid+1,r,q,pos*2+1);
up(l,r,pos);
}
}T;
void dfs1(int pos,int fa)
{
int maxn=0;
deep[pos]=deep[fa]+1,size[pos]=1,fat[pos]=fa;
for(int i=0;i<to[pos].size();i++)
{
int v=to[pos][i];
if(v==fa) continue;
dfs1(v,pos);
if(size[v]>maxn) maxn=size[v],hs[pos]=v;
size[pos]+=size[v];
}
}
void dfs2(int pos,int topx,int fa)
{
top[pos]=topx,dfn[pos]=++cnt,trk[cnt]=pos;
if(hs[pos]==0) return;
dfs2(hs[pos],topx,pos);
for(int i=0;i<to[pos].size();i++)
{
int v=to[pos][i];
if(v==fa||v==hs[pos]) continue;
dfs2(v,v,pos);
}
}
int require(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans+=T.query(1,n,dfn[top[x]],dfn[x],1);
int ka=T.find(1,n,dfn[top[x]],1);
int kb=T.find(1,n,dfn[fat[top[x]]],1);
if(ka==kb) ans--;
x=fat[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
// cout<<ans<<"aaa\n";
ans+=T.query(1,n,dfn[x],dfn[y],1);
// cout<<ans<<"aaa\n";
return ans;
}
void updated(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
T.update(1,n,dfn[top[x]],dfn[x],1,z);
x=fat[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
T.update(1,n,dfn[x],dfn[y],1,z);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
to[u].push_back(v);
to[v].push_back(u);
}
dfs1(1,0);dfs2(1,1,0);
T.build(1,n,1);
while(m--)
{
int x,y,z;
char opt;
cin>>opt;
if(opt=='Q')
{
cin>>x>>y;
cout<<require(x,y)<<"\n";
}
else
{
cin>>x>>y>>z;
updated(x,y,z);
}
}
return 0;
}