rt,码风相当清晰/kel
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, dfn[N], rk[N], w[N], a, b, c, idx, u, v, k;
int top[N], dep[N], f[N], heavy[N], siz[N];
char opt;
vector<int> g[N];
void dfs1(int u, int fa)
{
f[u] = fa, siz[u] = 1;
dep[u] = dep[fa] + 1;
for(auto v : g[u])
{
if(v == fa) continue;
dfs1(v, u), siz[v] += siz[u];
if(siz[v] > siz[heavy[u]]) heavy[u] = v;
}
return;
}
void dfs2(int u, int tp)
{
top[u] = tp, dfn[u] = ++idx;
rk[dfn[u]] = u;
if(!heavy[u]) return;
dfs2(heavy[u], tp);
for(auto v : g[u])
if(v != f[u] && v != heavy[u]) dfs2(v, v);
return;
}
struct node
{
int l, r, cl, cr, val, tag;
} tree[N << 2];
void pushup(int x)
{
if(tree[x].l == tree[x].r) return;
tree[x].val = tree[x << 1].val + tree[x << 1 | 1].val;
tree[x].val -= (tree[x << 1].cr == tree[x << 1 | 1].cl);
tree[x].cl = tree[x << 1].cl;
tree[x].cr = tree[x << 1 | 1].cr;
return;
}
void pushdown(int x)
{
if(!tree[x].tag) return;
tree[x << 1].tag = tree[x << 1 | 1].tag = tree[x].tag;
tree[x << 1].cl = tree[x << 1 | 1].cl = tree[x].tag;
tree[x << 1].cr = tree[x << 1 | 1].cr = tree[x].tag;
tree[x << 1].val = tree[x << 1 | 1].val = 1;
tree[x].tag = 0;
return;
}
void build(int l, int r, int x)
{
tree[x] = {l, r, 0, 0, 0, 0};
if(l == r)
{
tree[x].cl = tree[x].cr = w[rk[l]];
tree[x].val = 1;
return;
}
int mid = (l + r) >> 1;
build(l, mid, x << 1);
build(mid + 1, r, x << 1 | 1);
pushup(x);
return;
}
void update(int l, int r, int k, int x)
{
if(l <= tree[x].l && tree[x].r <= r)
{
tree[x].cl = tree[x].cr = tree[x].tag = k;
tree[x].val = 1;
return;
}
int mid = (tree[x].l + tree[x].r) >> 1;
pushdown(x);
if(l <= mid) update(l, r, k, x << 1);
if(mid < r) update(l, r, k, x << 1 | 1);
pushup(x);
return;
}
struct noti
{
int cl, cr, val;
};
noti merge(noti x, noti y)
{
return (noti) {x.cl, y.cr, x.val + y.val - (x.cr == y.cl)};
}
int query_col(int p, int x)
{
if(p <= tree[x].l && tree[x].r <= p) return tree[x].cl;
int mid = (tree[x].l + tree[x].r) >> 1;
pushdown(x);
if(p <= mid) return query_col(p, x << 1);
else return query_col(p, x << 1 | 1);
}
noti query(int l, int r, int x)
{
if(l <= tree[x].l && tree[x].r <= r)
return {tree[x].cl, tree[x].cr, tree[x].val};
int mid = (tree[x].l + tree[x].r) >> 1;
pushdown(x);
if(l <= mid && mid < r) return merge(query(l, r, x << 1), query(l, r, x << 1 | 1));
else if(l <= mid) return query(l, r, x << 1);
else return query(l, r, x << 1 | 1);
}
void modify(int x, int y, int k)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
update(dfn[top[x]], dfn[x], k, 1);
x = f[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
update(dfn[y], dfn[x], k, 1);
return;
}
int ask(int x, int y)
{
int res = 0;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res += query(dfn[top[x]], dfn[x], 1).val;
res -= (query_col(dfn[top[x]], 1) == query_col(dfn[f[top[x]]], 1));
x = f[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
res += query(dfn[y], dfn[x], 1).val;
return res;
}
int main()
{
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> w[i];
for(int i = 1; i < n; i++)
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
for(int i = 1; i <= m; i++)
{
cin >> opt;
if(opt == 'C')
{
cin >> a >> b >> c;
modify(a, b, c);
}
else
{
cin >> a >> b;
cout << ask(a, b) << '\n';
}
}
return 0;
}