#include<bits/stdc++.h>
#define mid ((l + r) >> 1)
using namespace std;
const int N = 200005;
vector <int> e[N];
int a[N], n, lll;
int top[N], dep[N], son[N], size[N], f[N];
int dfn[N], wz[N];
char c;
void dfs1(int x, int fa)
{
f[x] = fa;
dep[x] = dep[fa] + 1;
size[x] = 1;
for (auto i : e[x])
{
if (i == fa)
continue;
dfs1(i, x);
size[x] += size[i];
if(size[son[x]] < size[i])
son[x] = i;
}
return;
}
void dfs2(int x, int t)
{
dfn[x] = ++lll;
wz[lll] = x;
top[x] = t;
if (!son[x])
return;
dfs2(son[x], t);
for(auto i : e[x])
{
if (i == f[x] || i == son[x])
continue;
dfs2(i, i);
}
}
struct p
{
int a, b, c;
};
class Tree
{
private:
int sum[N << 2], lef[N << 2], rig[N << 2];
public:
void build(int root, int l, int r)
{
if (l == r)
{
lef[root] = rig[root] = a[wz[l]];
sum[root] = 1;
return;
}
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
if (rig[root << 1] == lef[root << 1 | 1])
sum[root] = sum[root << 1] + sum[root << 1 | 1] - 1;
else
sum[root] = sum[root << 1] + sum[root << 1 | 1];
lef[root] = lef[root << 1];
rig[root] = rig[root << 1 | 1];
}
void push_down(int root)
{
if(sum[root] == 1)
{
sum[root << 1] = sum[root << 1 | 1] = 1;
lef[root << 1] = lef[root << 1 | 1] = rig[root << 1] = rig[root << 1 | 1] = lef[root];
}
return;
}
void change(int root, int l, int r, int c)
{
sum[root] = 1;
lef[root] = rig[root] = c;
push_down(root);
return;
}
void update(int root, int l, int r, int x, int y, int c)
{
if (l >= x && r <= y)
{
change(root, l, r, c);
return;
}
push_down(root);
if (y > mid)
update(root << 1 | 1, mid + 1, r, x, y, c);
if (x <= mid)
update(root << 1, l, mid, x, y, c);
if (rig[root << 1] == lef[root << 1 | 1])
sum[root] = sum[root << 1] + sum[root << 1 | 1] - 1;
else
sum[root] = sum[root << 1] + sum[root << 1 | 1];
lef[root] = lef[root << 1];
rig[root] = rig[root << 1 | 1];
return;
}
p query(int root, int l, int r, int x, int y)
{
if (l >= x && r <= y)
{
return {sum[root], lef[root], rig[root]};
}
this->push_down(root);
p a = {0, 0, 0}, b = {0, 0, 0};
if (y > mid)
b = query(root << 1 | 1, mid + 1, r, x, y);
if (x <= mid)
a = query(root << 1, l, mid, x, y);
if (rig[root << 1] == lef[root << 1 | 1])
sum[root] = sum[root << 1] + sum[root << 1 | 1] - 1;
else
sum[root] = sum[root << 1] + sum[root << 1 | 1];
lef[root] = lef[root << 1];
rig[root] = rig[root << 1 | 1];
if (a.a && b.a)
{
if (rig[root << 1] == lef[root << 1 | 1])
return {a.a + b.a - 1, a.b, b.c};
return {a.a + b.a, a.b, b.c};
}
else if (a.a)
return a;
else
return b;
}
}tree;
void update_lca(int x, int y, int z)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
tree.update(1, 1, n, dfn[top[x]], dfn[x], z);
x = f[top[x]];
}
if (dfn[x] > dfn[y])
swap(x, y);
tree.update(1, 1, n, dfn[x], dfn[y], z);
}
int lca(int x, int y)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
x = f[top[x]];
}
if (dep[x] < dep[y])
return x;
else
return y;
}
int query_lca(int x, int y)
{
int ans = 0, fa = lca(x, y), ff;
ff = fa;
p u = {-1, -1, -1}, v;
while (top[x] != top[fa])
{
if (dep[top[x]] < dep[top[fa]])
swap(x, fa);
v = u;
u = tree.query(1, 1, n, dfn[top[x]], dfn[x]);
if (v.c == u.b)
ans--;
ans += u.a;
x = f[top[x]];
}
v = u;
u = tree.query(1, 1, n, dfn[fa], dfn[x]);
if (v.c == u.b)
ans--;
ans += u.a;
fa = ff;
u = {-1, -1, -1};
while (top[y] != top[fa])
{
if (dep[top[y]] < dep[top[fa]])
swap(y, fa);
v = u;
u = tree.query(1, 1, n, dfn[top[y]], dfn[y]);
if (v.c == u.b)
ans--;
ans += u.a;
y = f[top[y]];
}
v = u;
u = tree.query(1, 1, n, dfn[fa], dfn[y]);
if (v.c == u.b)
ans--;
ans += u.a;
return ans - 1;
}
int q, x, y, z;
int main()
{
cin >> n >> q;
for(int i = 1; i <= n; i++)
scanf("%d", a + i);
for (int i = 1, u, v; i < n; i++)
{
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1, 0);
dfs2(1, 1);
tree.build(1, 1, n);
while(q--)
{
cin >> c;
if (c == 'Q')
{
scanf("%d%d",&x, &y);
printf("%d\n", query_lca(x, y));
}
else
{
scanf("%d%d%d", &x, &y, &z);
update_lca(x, y, z);
}
}
}