#include <bits/stdc++.h>
#define pb push_back
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
using namespace std;
using ll = long long;
const int maxn = 1e5 + 5;
ll n, q, u, v, k; char opt;
ll val[maxn], dep[maxn], fat[maxn], top[maxn], son[maxn], siz[maxn], ide[maxn];
vector <ll> G[maxn];
ll tot, a[maxn], tag[maxn << 2];
struct node {
ll le, ri, cnt;
inline void init() {
le = ri = cnt = -1;
return;
}
inline node sawp() {
return node{ri, le, cnt};
}
friend bool operator == (node a, node b) {
return a.le == b.le && a.ri == b.ri && a.cnt == b.cnt;
}
friend node operator + (node a, node b) {
if (a == node{-1, -1, -1}) return b;
if (b == node{-1, -1, -1}) return a;
return node{a.le, b.ri, a.cnt + b.cnt - (a.ri == b.le ? 1 : 0)};
}
} t[maxn << 2];
void dfs1(ll u, ll fa) {
dep[u] = dep[fa] + 1;
fat[u] = fa;
siz[u] = 1;
for (auto g : G[u]) {
if (g == fa) continue;
dfs1(g, u);
if (siz[son[u]] < siz[g]) {
son[u] = g;
}
siz[u] += siz[g];
}
return;
}
void dfs2(ll u, ll T) {
top[u] = T;
ide[u] = ++tot;
a[tot] = val[u];
if (son[u]) dfs2(son[u], T);
for (auto g : G[u]) {
if (g == fat[u] || g == son[u]) continue;
dfs2(g, g);
}
return;
}
void build(ll l, ll r, ll i) {
tag[i] = -1;
if (l == r) {
t[i] = {a[l], a[r], 1};
return;
}
build(l, mid, ls);
build(mid + 1, r, rs);
t[i] = t[ls] + t[rs];
// cout << l << ' ' << r << ' ' << t[i].le << ' ' << t[i].ri << ' ' << t[i].cnt << '\n';
return;
}
inline void apply(ll i, ll v) {
if (v == -1) return;
tag[i] = v;
t[i].le = t[i].ri = v;
t[i].cnt = 1;
return;
}
inline void pushdown(ll i) {
apply(ls, tag[i]);
apply(rs, tag[i]);
return;
}
void update(ll l, ll r, ll i, ll a, ll b, ll k) {
if (a <= l && r <= b) {
apply(i, k);
return;
}
pushdown(i);
if (a <= mid) update(l, mid, ls, a, b, k);
if (mid < b) update(mid + 1, r, rs, a, b, k);
t[i] = t[ls] + t[rs];
return;
}
node query(ll l, ll r, ll i, ll a, ll b) {
if (a <= l && r <= b) return t[i];
node ans; ans.init();
if (a <= mid) ans = ans + query(l, mid, ls, a, b);
if (mid < b) ans = ans + query(mid + 1, r, rs, a, b);
return ans;
}
ll lca(ll u, ll v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = fat[top[u]];
}
return dep[u] > dep[v] ? v : u;
}
void lca_update(ll u, ll v, ll k) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
update(1, n, 1, ide[top[u]], ide[u], k);
u = fat[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
update(1, n, 1, ide[v], ide[u], k);
return;
}
ll lca_query(ll u, ll v) {
node a1, a2, b, ans; a1.init(); a2.init();
ll Lca = lca(u, v);
while (top[u] != top[Lca]) {
b = query(1, n, 1, ide[top[u]], ide[u]);
a1 = b + a1;
// cout << "a1:" << ide[top[u]] << ' ' << ide[u] << '\n';
// cout << b.le << ' ' << b.ri << ' ' << b.cnt << "\n\n";
u = fat[top[u]];
}
while (top[v] != top[Lca]) {
b = query(1, n, 1, ide[top[v]], ide[v]).sawp();
a2 = b + a2;
// cout << "a2:" << ide[top[v]] << ' ' << ide[v] << '\n';
// cout << b.le << ' ' << b.ri << ' ' << b.cnt << "\n\n";
v = fat[top[v]];
}
if (u == Lca) {
b = query(1, n, 1, ide[u], ide[v]).sawp();
a2 = b + a2;
// cout << "a2:" << ide[u] << ' ' << ide[v] << '\n';
// cout << b.le << ' ' << b.ri << ' ' << b.cnt << "\n\n";
} else {
b = query(1, n, 1, ide[v], ide[u]);
a1 = b + a1;
// cout << "a1:" << ide[v] << ' ' << ide[u] << '\n';
// cout << b.le << ' ' << b.ri << ' ' << b.cnt << "\n\n";
}
ans = a1 + a2;
return ans.cnt;
}
void ch(ll l, ll r, ll i) {
cout << l << ' ' << r << ' ' << t[i].le << ' ' << t[i].ri << ' ' << t[i].cnt << '\n';
if (l == r) return;
ch(l, mid, ls);
ch(mid + 1, r, rs);
return;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> val[i];
}
for (int i = 1; i < n; i++) {
cin >> u >> v;
G[u].pb(v); G[v].pb(u);
}
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
// for (int i = 1; i <= n; i++) {
// cout << "Id " << i << " ide " << ide[i] << " a " << a[ide[i]] << '\n';
// }
for (int i = 1; i <= q; i++) {
cin >> opt >> u >> v;
if (opt == 'Q') {
cout << lca_query(u, v) << '\n';
} else {
cin >> k;
lca_update(u, v, k);
}
}
return 0;
}
/*
2 1 1 1 1 1
1 2 4 6 5 3
*/
真是有点母亲!