#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 5;
using namespace std;
struct node {
int lcol, rcol, sum;
node operator + (node b) const {
node res;
res.lcol = this -> lcol;
res.rcol = b.rcol;
res.sum = this -> sum + b.sum;
if (this -> rcol == b.lcol) res.sum --;
if (res.lcol == 0) res.lcol = b.lcol;
if (res.rcol == 0) res.rcol = this -> rcol;
return res;
}
void clear () {
this -> lcol = 0;
this -> rcol = 0;
this -> sum = 0;
return;
}
} tree[N << 2];
int n, m;
int tag[N << 2];
vector <int> G[N];
int NOW, dfn[N], cr[N], col[N], fa[N];
int dep[N], top[N], son[N], mx[N];
void dfs1 (int u, int lst) {
son[u] = 1;
dep[u] = dep[lst] + 1;
fa[u] = lst;
for (int i = 0 ; i < G[u].size() ; i ++) {
int v = G[u][i];
if (v != lst) {
dfs1 (v, u);
son[u] += son[v];
if (son[mx[u]] < son[v]) mx[u] = v;
}
}
return;
}
void dfs2 (int u, int lst) {
dfn[u] = ++ NOW;
cr[NOW] = u;
if (mx[u]) {
top[mx[u]] = top[u];
dfs2 (mx[u], u);
}
for (int i = 0 ; i < G[u].size() ; i ++) {
int v = G[u][i];
if (v != lst && v != mx[u])
dfs2 (v, u);
}
return;
}
void push_down (int p) {
if (tag[p]) {
tree[p << 1].lcol = tree[p << 1 | 1].lcol = tag[p];
tree[p << 1].rcol = tree[p << 1 | 1].rcol = tag[p];
tree[p << 1].sum = tree[p << 1 | 1].sum = 1;
tag[p << 1] = tag[p];
tag[p << 1 | 1] = tag[p];
tag[p] = 0;
}
return;
}
void build (int p, int l, int r) {
if (l == r) {
tree[p].lcol = col[cr[l]];
tree[p].rcol = col[cr[l]];
tree[p].sum = 1;
return;
}
int mid = l + r >> 1;
build (p << 1, l, mid);
build (p << 1 | 1, mid + 1, r);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
return;
}
void update (int p, int pl, int pr, int l, int r, int k) {
if (l > r) swap (l, r);
if (pl >= l && pr <= r) {
tree[p].lcol = tree[p].rcol = k;
tree[p].sum = 1;
tag[p] = k;
return;
}
push_down(p);
int mid = pl + pr >> 1;
if (mid >= l) update(p << 1, pl, mid, l, r, k);
if (mid < r) update(p << 1 | 1, mid + 1, pr, l, r, k);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
return;
}
node query (int p, int pl, int pr, int l, int r) {
if (l > r) swap (l, r);
if (pl >= l && pr <= r) return tree[p];
node res;
res.clear();
int mid = pl + pr >> 1;
push_down(p);
if (mid >= l) res = res + query (p << 1, pl, mid, l, r);
if (mid < r) res = res + query (p << 1 | 1, mid + 1, pr, l, r);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
return res;
}
void updateRange (int x, int y, int k) {
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]]) swap(x, y);
update (1, 1, n, dfn[y], dfn[top[y]], k);
y = fa[top[y]];
}
update (1, 1, n, dfn[x], dfn[y], k);
return;
}
queue <node> q1;
stack <node> q2;
int queryRange (int x, int y) {
node res;
res.clear();
bool flag = 0;
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]]) {
swap(x, y);
flag = !flag;
}
if (!flag) q1.push(query(1, 1, n, dfn[y], dfn[top[y]]));
else q2.push(query(1, 1, n, dfn[y], dfn[top[y]]));
y = fa[top[y]];
}
if (dep[x] > dep[y]) flag = !flag;
if (!flag) q1.push(query(1, 1, n, dfn[x], dfn[y]));
else q2.push(query(1, 1, n, dfn[x], dfn[y]));
while (!q1.empty()) {
res = res + q1.front();
q1.pop();
}
while (!q2.empty()) {
res = res + q2.top();
q2.pop();
}
return res.sum;
}
signed main () {
cin >> n >> m;
for (int i = 1 ; i <= n ; i ++) cin >> col[i];
int k = n - 1;
while (k --) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs1 (1, 1);
for (int i = 1 ; i <= n ; i ++) top[i] = i;
dfs2 (1, 1);
build (1, 1, n);
while (m --) {
char op;
cin >> op;
if (op == 'C') {
int a, b, c;
cin >> a >> b >> c;
updateRange(a, b, c);
} else {
int a, b;
cin >> a >> b;
cout << queryRange(a, b) << '\n';
}
}
return 0;
}