拍了20000组没发现问题。。。
#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define pll pair<ll,ll>
#define ull unsigned long long
#define int long long
using namespace std;
const int N=1e5+5;
const long long LINF=0x3f3f3f3f3f3f3f3fll;
const int IINF=0x3f3f3f3f;
inline void FileIO() {
freopen(".in","r",stdin);
freopen(".out","w",stdout);
}
template<typename Type>
inline void read(Type& res) {
Type x=0,f=1;
char c=' ';
while(!isdigit(c)) {
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
res=x*f;
}
int n,Q,a[N];
int dfn[N],id[N],son[N],dep[N],top[N],siz[N],fa[N];
int head[N],tot,cnt;
struct Edge{
int to,nxt;
}edge[N<<1];
void Add(int u,int v){
edge[++tot].to=v;
edge[tot].nxt=head[u];
head[u]=tot;
}
void Debug(){
for(int i=1;i<=n;i++){
// printf("Tree[%d]: dfn=%d,son=%d,dep=%d,top=%d,siz=%d\n",i,dfn[i],son[i],dep[i],top[i],siz[i]);
}
}
struct Segtr{
int l,r;
int val,cl,cr,cov;
bool st;
}tr[N<<2],ept;
struct SegmentTree{
void Pushup(Segtr& p,Segtr s1,Segtr s2){
p.cl=s1.cl,p.cr=s2.cr;
p.val=s1.val+s2.val;
if(s1.cr==s2.cl) p.val--;
}
void Spread(int p){
if(tr[p].st){
tr[p<<1].cov=tr[p<<1|1].cov=tr[p].cov;
tr[p<<1].cl=tr[p<<1|1].cl=tr[p].cov;
tr[p<<1].cr=tr[p<<1|1].cr=tr[p].cov;
tr[p<<1].st=tr[p<<1|1].st=1;
tr[p<<1].val=tr[p<<1|1].val=1;
tr[p].cov=tr[p].st=0;
}
}
void Buildtr(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
if(l==r){
tr[p].val=1;
tr[p].cl=tr[p].cr=a[id[l]];
return;
}
int mid=(l+r)>>1;
Buildtr(p<<1,l,mid);
Buildtr(p<<1|1,mid+1,r);
Pushup(tr[p],tr[p<<1],tr[p<<1|1]);
}
void Cover(int p,int l,int r,int w){
if(l<=tr[p].l&&tr[p].r<=r){
tr[p].val=tr[p].st=1;
tr[p].cov=tr[p].cl=tr[p].cr=w;
return;
}
Spread(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid) Cover(p<<1,l,r,w);
if(r>mid) Cover(p<<1|1,l,r,w);
Pushup(tr[p],tr[p<<1],tr[p<<1|1]);
}
Segtr Ask(int p,int l,int r){
if(l<=tr[p].l&&tr[p].r<=r) return tr[p];
Spread(p);
int mid=(tr[p].l+tr[p].r)>>1;
Segtr res=ept;
if(l<=mid&&r>mid){
Pushup(res,Ask(p<<1,l,r),Ask(p<<1|1,l,r));
return res;
}
else if(l<=mid) return Ask(p<<1,l,r);
else return Ask(p<<1|1,l,r);
}
void PrintTr(){
for(int i=1;i<=13;i++){
if(!tr[i].l) continue;
// printf("SegTr[%d]: [%d,%d],val=%d,cl=%d,cr=%d,cov=%d\n",i,tr[i].l,tr[i].r,tr[i].val,tr[i].cl,tr[i].cr,tr[i].cov);
}
}
}Seg;
struct TreeCut{
void dfs1(int x,int pr){
dep[x]=dep[pr]+1;
siz[x]=1;
fa[x]=pr;
int mx=0;
for(int i=head[x];i;i=edge[i].nxt){
int t=edge[i].to;
if(t==pr) continue;
dfs1(t,x);
siz[x]+=siz[t];
if(mx<siz[t]) mx=siz[t],son[x]=t;
}
}
void dfs2(int x,int pr,int s){
dfn[x]=++cnt;
id[cnt]=x;
top[x]=s;
if(!son[x]) return;
dfs2(son[x],x,s);
for(int i=head[x];i;i=edge[i].nxt){
int t=edge[i].to;
if(t==pr||t==son[x]) continue;
dfs2(t,x,t);
}
}
void CoverPath(int u,int v,int w){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
Seg.Cover(1,dfn[top[u]],dfn[u],w);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
Seg.Cover(1,dfn[u],dfn[v],w);
}
int AskPath(int U,int V){
pii u=make_pair(U,-1);
pii v=make_pair(V,-1);
int ans=0;
while(top[u.first]!=top[v.first]){
if(dep[top[u.first]]<dep[top[v.first]]) swap(u,v);
Segtr res=Seg.Ask(1,dfn[top[u.first]],dfn[u.first]);
ans+=res.val;
if(res.cr==u.second) ans--;
u=make_pair(fa[top[u.first]],res.cl);
}
if(dep[u.first]>dep[v.first]) swap(u,v);
Segtr res=Seg.Ask(1,dfn[u.first],dfn[v.first]);
ans+=res.val;
if(res.cl==u.second) ans--;
if(res.cr==v.second) ans--;
return ans;
}
}Chain;
signed main(){
// 不开longlong见祖宗!
// 检查数组大小!
// 禁止在int乘int时不开longlong!
// 注意输出格式!
// STL数据类型拷贝赋值时间复杂度是 O(N)!
// 读入单个字符要用字符串,防毒瘤数据!
// (1<<63)爆ll,(1<<31)爆int!
// 比赛结束前5min,检查上述7项,并编译运行!!!!!
// -std=c++14 -O2 -Wall -Wextra -Wshadow -Wl,--stack=536870912
read(n),read(Q);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<n;i++){
int u,v;
read(u),read(v);
Add(u,v);
Add(v,u);
}
Chain.dfs1(1,0);
Chain.dfs2(1,0,1);
// Debug();
Seg.Buildtr(1,1,n);
while(Q--){
char op[3],x,y,w;
scanf("%s",op);
if(op[0]=='C'){
read(x),read(y),read(w);
Chain.CoverPath(x,y,w);
}
else{
read(x),read(y);
printf("%lld\n",Chain.AskPath(x,y));
}
// Seg.PrintTr();
}
return 0;
}