#include <clocale>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maxn = 1e5+10;
vector<int> G[maxn];
int w[maxn], pa[maxn], son[maxn], siz[maxn], dep[maxn];
int top[maxn], rnk[maxn], dfn[maxn], lst[maxn];
int n, q;
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
struct Node{
int l, r;
int lcol, rcol;
int cnt;
};
int lptr, rptr, lc, rc;
struct Seg{
Node nodes[maxn*4];
void expand(int uid){
Node& u = nodes[uid];
if(u.l == u.r) return;
Node& l = nodes[ls(uid)];
Node& r = nodes[rs(uid)];
if(u.cnt == 1){
l.cnt = r.cnt = 1;
l.lcol = l.rcol = r.rcol = r.lcol = u.lcol;
}
}
void upd(int u){
if(nodes[u].l == nodes[u].r) return;
nodes[u].cnt = nodes[ls(u)].cnt + nodes[rs(u)].cnt;
if(nodes[ls(u)].rcol == nodes[rs(u)].lcol) nodes[u].cnt--;
nodes[u].lcol = nodes[ls(u)].lcol; nodes[u].rcol = nodes[rs(u)].rcol;
}
void build(int l, int r, int uid){
Node& u = nodes[uid];
u.l = l, u.r = r;
if(l == r){
u.cnt = 1;
u.lcol = u.rcol = w[dfn[l]];
return;
}
int m = (l+r)>>1;
build(l, m, ls(uid));
build(m+1, r, rs(uid));
upd(uid);
}
void set(int t, int l, int r, int uid){
Node& u = nodes[uid];
if(l <= u.l && u.r <= r){
u.lcol = u.rcol = t;
u.cnt = 1;
return;
}
expand(uid);
if(u.l == u.r) return;
int m = (u.l + u.r) >> 1;
if(l <= nodes[ls(uid)].r) set(t, l, r, ls(uid));
if(r >= nodes[rs(uid)].l) set(t, l, r, rs(uid));
upd(uid);
}
int querycnt(int l, int r, int u){
{
if(nodes[u].l == lptr)
lc = nodes[u].lcol;
if(nodes[u].r == rptr)
rc = nodes[u].rcol;
if(nodes[u].r == lptr)
lc = nodes[u].rcol;
if(nodes[u].l == rptr)
rc = nodes[u].lcol;
}
if(nodes[u].l >= l && nodes[u].r <= r) return nodes[u].cnt;
expand(u);
int ans = 0, lcol = -1;
if(nodes[u].l == nodes[u].r){
return 1;
}
if(l <= nodes[ls(u)].r){
ans = querycnt(l, r, ls(u));
lcol = nodes[ls(u)].rcol;
}
if(r >= nodes[rs(u)].l){
ans += querycnt(l, r, rs(u));
if(lcol == nodes[rs(u)].lcol) ans--;
}
return ans;
}
}sgt;
void pre(int u){
siz[u] = 1;
son[u] = -1;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(v == pa[u]) continue;
pa[v] = u;
dep[v] = dep[u]+1;
pre(v);
if(son[u] == -1 || siz[v] > siz[son[u]])son[u] = v;
siz[u] += siz[v];
}
}
int cnt = 0;
void dfs(int u, int tp){
cnt++;
rnk[u] = cnt;
dfn[cnt] = u;
top[u] = tp;
lst[u] = cnt;
if(son[u] != -1){
dfs(son[u], tp);
}
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(v == pa[u] || v == son[u]) continue;
dfs(v, v);
}
}
int query(int x, int y){
int ans = 0, xcol = -1, ycol = -1;
while(top[x] != top[y]){
if(dep[top[x]] > dep[top[y]]){
lptr = rnk[top[x]], rptr = rnk[x];
ans += sgt.querycnt(rnk[top[x]], rnk[x], 1);
if(xcol == rc) ans --;
xcol = lc;
x=pa[top[x]];
}
else {
lptr = rnk[top[y]], rptr = rnk[y];
ans += sgt.querycnt(rnk[top[y]], rnk[y], 1);
if(ycol == rc) ans --;
ycol = lc;
y=pa[top[y]];
}
}
if(dep[x] > dep[y]) {
swap(x, y);
swap(xcol, ycol);
}
lptr = rnk[x], rptr = rnk[y];
ans += sgt.querycnt(rnk[x], rnk[y], 1);
if(lc == xcol) ans--;
if(rc == ycol) ans--;
return ans;
}
void set(int col, int x, int y){
while(top[x] != top[y]){
if(dep[x] > dep[y]){
sgt.set(col, rnk[top[x]], rnk[x], 1);
x = pa[top[x]];
}
else{
sgt.set(col, rnk[top[y]], rnk[y], 1);
y = pa[top[y]];
}
}
if(dep[x] != dep[y]){
if(dep[x] > dep[y]){
swap(x, y);
}
sgt.set(col, rnk[x], rnk[y], 1);
}
}
int main(){
cin >> n >> q;
for(int i = 1; i <= n; i++)
cin >> w[i];
for(int i = 1; i < n; i++){
int a, b; cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
pre(1);
dfs(1, 1);
sgt.build(1, n, 1);
while(q--){
string s; cin >> s;
if(s == "C"){
int a, b, c;
cin >> a >> b >> c;
set(c, a, b);
}
if(s == "Q"){
int a, b;
cin >> a >> b;
cout << query(a, b) << endl;
}
}
return 0;
}