维护一个区间里的颜色段个数,左端点颜色,右端点颜色和修改标记。
对于区间[a,b]和[b+1,c],它们的颜色段个数分别为x,y,如果b颜色和b+1颜色相同,那么[a,c]颜色段个数为x+y-1,否则为x+y。
树上深度浅的点dfs序要小一些。一个区间左端点就对应树上深度小的一个点,右端点对应树上深度大一些的一个点,。
跳重链时,用一个数记录上次跳的链的左端点,和当前所在链的右端点比较。
两个点跳到同一条重链上的时候,路径的两个端点都要判一下。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char op[10];
int n,m,a,b,c;
int t[maxn],dfn[maxn],tot;
int col[maxn],son[maxn],fa[maxn],sz[maxn],dep[maxn],top[maxn];
int cnt=0,Head[maxn],Next[maxn<<1],V[maxn<<1];
struct node{
int cl,cr;
int cov,num;
node(){cov=-1;}
}T[maxn<<2];
int read(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
void print(int x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
void add(int u,int v){++cnt,Next[cnt]=Head[u],V[cnt]=v,Head[u]=cnt;}
void dfs1(int u,int f){
sz[u]=1,son[u]=0;
for(int i=Head[u];i;i=Next[i]){
if(V[i]==f) continue;
dep[V[i]]=dep[u]+1,fa[V[i]]=u;
dfs1(V[i],u),sz[u]+=sz[V[i]];
if(sz[son[u]]<sz[V[i]]) son[u]=V[i];
}
}
void dfs2(int u,int tp){
top[u]=tp,dfn[u]=++tot,t[tot]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=Head[u];i;i=Next[i])
if(V[i]!=fa[u]&&V[i]!=son[u])
dfs2(V[i],V[i]);
}
node pushup(node Tl,node Tr){
node ret;
ret.num=Tl.num+Tr.num-(Tl.cr==Tr.cl);
ret.cl=Tl.cl,ret.cr=Tr.cr;
return ret;
}
void pushnow(int root,int val){T[root].cl=T[root].cr=T[root].cov=val,T[root].num=1;}
void pushdown(int root){
if(T[root].cov==-1) return;
pushnow(root<<1,T[root].cov),pushnow(root<<1|1,T[root].cov);
T[root].cov=-1;
}
void build(int root,int l,int r){
if(l==r){T[root].cl=T[root].cr=col[t[l]],T[root].num=1;return;}
int mid=(l+r)>>1;
build(root<<1,l,mid),build(root<<1|1,mid+1,r);
T[root]=pushup(T[root<<1],T[root<<1|1]);
}
node query(int root,int l,int r,int x,int y){
if(l>=x&&r<=y) return T[root];
pushdown(root);
int mid=(l+r)>>1;
if(y<=mid) return query(root<<1,l,mid,x,y);
if(x>mid) return query(root<<1|1,mid+1,r,x,y);
return pushup(query(root<<1,l,mid,x,y),query(root<<1|1,mid+1,r,x,y));
}
void change(int root,int l,int r,int x,int y,int val){
if(l>=x&&r<=y){
pushnow(root,val);
return;
}
pushdown(root);
int mid=(l+r)>>1;
if(x<=mid) change(root<<1,l,mid,x,y,val);
if(y>mid) change(root<<1|1,mid+1,r,x,y,val);
T[root]=pushup(T[root<<1],T[root<<1|1]);
}
int ask(int x,int y){
int ans=0,xl=0,yl=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(xl,yl);
node now=query(1,1,n,dfn[top[x]],dfn[x]);
ans=ans+now.num-(now.cr==xl);
xl=now.cl,x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y),swap(xl,yl);
node now=query(1,1,n,dfn[x],dfn[y]);
ans=ans+now.num-(xl==now.cl)-(yl==now.cr);
return ans;
}
void modify(int x,int y,int val){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(1,1,n,dfn[top[x]],dfn[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(1,1,n,dfn[x],dfn[y],val);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i) col[i]=read();
for(int i=1;i<n;++i) a=read(),b=read(),add(a,b),add(b,a);
dfs1(1,0),dfs2(1,1),build(1,1,n);
while(m--){
scanf("%s",op);
if(op[0]=='Q'){
a=read(),b=read();
print(ask(a,b)),putchar('\n');
}
if(op[0]=='C'){
a=read(),b=read(),c=read();
modify(a,b,c);
}
}
}