RT
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100005],u,v,dep[100005],son[100005],size[100005];
int top[100005],p[100005],sum[100005],f[100005],cnt;
vector<int>ve[100005];
struct node {
int s,lazy,l,r;
} tree[100005<<2|1],temp;
node add(node x,node y) {
node res;
res.l=x.l;
res.r=y.r;
res.s=x.s+y.s;
if(x.r==y.l)res.s--;
res.lazy=0;
return res;
}
void push_up(int p) {
tree[p]=add(tree[p<<1],tree[p<<1|1]);
}
void push_down(int p) {
if(!tree[p].lazy)return;
int ls=p<<1,rs=p<<1|1;
tree[ls].lazy=tree[p].lazy;
tree[rs].lazy=tree[p].lazy;
tree[ls].l=tree[p].lazy;
tree[ls].r=tree[p].lazy;
tree[rs].l=tree[p].lazy;
tree[rs].r=tree[p].lazy;
tree[ls].s=1;
tree[rs].s=1;
tree[p].lazy=0;
return;
}
void build(int l,int r,int p) {
if(l==r) {
tree[p].s=1;
tree[p].l=tree[p].r=sum[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,p<<1);
build(mid+1,r,p<<1|1);
push_up(p);
return;
}
void update(int l1,int r1,int l,int r,int p,int k) {
if(l>=l1&&r<=r1) {
tree[p].lazy=k;
tree[p].s=1;
tree[p].l=tree[p].r=k;
return;
}
int mid=(l+r)>>1;
push_down(p);
if(mid>=l1)update(l1,r1,l,mid,p<<1,k);
if(r1>mid)update(l1,r1,mid+1,r,p<<1|1,k);
push_up(p);
return;
}
node query(int l1,int r1,int l,int r,int p) {
if(l>=l1&&r<=r1)return tree[p];
int mid=(l+r)>>1;
push_down(p);
if(r1<=mid)return query(l1,r1,l,mid,p<<1);
if(l1>mid)return query(l1,r1,mid+1,r,p<<1|1);
return add(query(l1,r1,l,mid,p<<1),query(l1,r1,mid+1,r,p<<1|1));
}
void dfs1(int now,int fa,int deep) {
f[now]=fa;
dep[now]=deep;
size[now]=1;
int maxsize=0;
for(int i=0; i<ve[now].size(); i++) {
int y=ve[now][i];
if(y==fa)continue;
dfs1(y,now,deep+1);
size[now]+=size[y];
if(size[y]>maxsize)son[now]=y,maxsize=size[y];
}
return;
}
void dfs2(int now,int _top) {
top[now]=_top;
p[now]=++cnt;
sum[cnt]=a[now];
if(!son[now])return;
dfs2(son[now],_top);
for(int i=0; i<ve[now].size(); i++) {
int y=ve[now][i];
if(y==f[now]||y==son[now])continue;
dfs2(y,y);
}
return;
}
int query1(int x,int y) {
node res[10005];
int num=0;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]])swap(x,y);
res[++num]=query(p[top[x]],p[x],1,n,1);
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
res[++num]=query(p[x],p[y],1,n,1);
for(int i=2; i<=num; i++)res[i]=add(res[i-1],res[i]);
return res[num].s;
}
void update1(int x,int y,int z) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(p[top[x]],p[x],1,n,1,z);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
update(p[x],p[y],1,n,1,z);
}
signed main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)scanf("%d",&a[i]);
for(int i=1; i<n; i++) {
scanf("%d%d",&u,&v);
ve[u].push_back(v);
ve[v].push_back(u);
}
char opt;
int x,y,z;
dfs1(1,0,1);
dfs2(1,1);
build(1,n,1);
while(m--) {
cin>>opt;
if(opt=='Q') {
scanf("%d%d",&x,&y);
printf("%d\n",query1(x,y));
}
if(opt=='C') {
scanf("%d%d%d",&x,&y,&z);
update1(x,y,z);
}
}
}