rt,这题貌似也不用开 long long 啊
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1000005;
int n, Q;
int w[MAXN];
struct edge {
int to, nex;
}e[MAXN << 1]; int idx, head[MAXN];
inline void add(int u, int v) {
e[++ idx].to = v;
e[idx].nex = head[u];
head[u] = idx;
}
int timer, dfn[MAXN], id[MAXN];
int fa[MAXN], dep[MAXN], siz[MAXN];
int top[MAXN], wson[MAXN];
inline void dfs1(int u) {
siz[u] = 1;
if (u == 1) dep[u] = 1;
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].to;
if (v == fa[u]) continue;
fa[v] = u; dep[v] = dep[u] + 1;
dfs1(v); siz[u] += siz[v];
if (siz[v] > siz[wson[u]])
wson[u] = v;
}
}
inline void dfs2(int u, int bel) {
top[u] = bel;
id[dfn[u] = ++ timer] = u;
if (wson[u]) dfs2(wson[u], bel);
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].to;
if (v == fa[u] || v == wson[u])
continue;
dfs2(v, v);
}
}
class Segment_tree {
#define lc (u << 1)
#define rc (u << 1 | 1)
private :
struct node {
int lcl, rcl;
int sum, col;
}tr[MAXN << 2];
inline void push_up(int u) {
tr[u].lcl = tr[lc].lcl;
tr[u].rcl = tr[rc].rcl;
tr[u].sum = tr[lc].sum + tr[rc].sum;
if (tr[lc].rcl == tr[rc].lcl)
-- tr[u].sum;
}
inline void push_down(int u) {
if (!tr[u].col) return;
int tg = tr[u].col;
tr[u].col = 0;
tr[lc].col = tr[rc].col = tg;
tr[lc].lcl = tr[lc].rcl = tg;
tr[rc].lcl = tr[rc].rcl = tg;
tr[lc].sum = tr[rc].sum = 1;
}
public :
inline void Build(int u = 1, int l = 1, int r = n) {
if (l == r) {
tr[u].sum = 1;
tr[u].lcl = tr[u].rcl = w[id[l]];
return;
}
int mid = (l + r) >> 1;
Build(lc, l, mid);
Build(rc, mid + 1, r);
push_up(u);
}
inline void Modify(int bg, int nd, int x, int u = 1, int l = 1, int r = n) {
if (bg <= l && r <= nd) {
tr[u].col = x;
tr[u].lcl = tr[u].rcl = x;
tr[u].sum = 1;
return;
}
push_down(u);
int mid = (l + r) >> 1;
if (bg <= mid) Modify(bg, nd, x, lc, l, mid);
if (nd > mid) Modify(bg, nd, x, rc, mid + 1, r);
push_up(u);
}
inline int Query(int bg, int nd, int &lct, int &rct, int u = 1, int l = 1, int r = n) {
if (bg <= l && r <= nd) {
if (bg == l) lct = tr[u].lcl;
if (nd == r) rct = tr[u].rcl;
return tr[u].sum;
}
int mid = (l + r) >> 1;
push_down(u);
if (nd <= mid) return Query(bg, nd, lct, rct, lc, l, mid);
if (bg > mid) return Query(bg, nd, lct, rct, rc, mid + 1, r);
int res = Query(bg, nd, lct, rct, lc, l, mid);
res += Query(bg, nd, lct, rct, rc, mid + 1, r);
if (tr[lc].rcl == tr[rc].lcl) -- res;
return res;
}
#undef lc
#undef rc
}st;
inline void Chg(int u, int v, int col) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])
swap(u, v);
st.Modify(dfn[top[u]], dfn[u], col);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
st.Modify(dfn[u], dfn[v], col);
}
inline int Qry(int u, int v) {
int res = 0;
int lst1 = -1, lst2 = -1;
int Lt, Rt;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])
swap(u, v), swap(lst1, lst2);
res += st.Query(dfn[top[u]], dfn[u], Lt, Rt);
res -= (Rt == lst1); lst1 = Lt;
u = fa[top[u]];
}
if (dep[u] > dep[v])
swap(u, v);
res += st.Query(dfn[u], dfn[v], Lt, Rt);
if (Lt == lst1) -- res;
if (Rt == lst2) -- res;
return res;
}
int main()
{
scanf ("%d%d", &n, &Q);
for (int i = 1; i <= n; ++ i)
scanf ("%d", w + i);
for (int i = 1; i < n; ++ i) {
int u, v;
scanf ("%d%d", &u, &v);
add(u, v); add(v, u);
}
dfs1(1); dfs2(1, 1);
st.Build();
char op[MAXN];
int a, b, c;
while (Q --) {
scanf ("%s", op);
if (op[0] == 'C') {
scanf ("%d%d%d", &a, &b, &c);
Chg(a, b, c);
} else {
scanf ("%d%d", &a, &b);
printf ("%d\n", Qry(a, b));
}
}
return 0;
}