#include <iostream>
#define int long long
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
const int N = 1e6+10;
int n,m,dis[N],tlc,trc;
int dep[N],dfn[N],rnk[N],son[N],siz[N],top[N],fa[N],tot;
struct EDGE
{
int Head[N*2],Ver[N*2],Next[N*2],tot;
inline void add(int x,int y){
Ver[++tot]=y,Next[tot]=Head[x],Head[x]=tot;
}
}E;
namespace lineTree
{
struct Tree
{
int l,r,num,lc,rc,tag;
}t[N*4];
inline void pushUp(int x)
{
t[x].lc=t[ls].lc,t[x].rc=t[rs].rc;
if(t[ls].rc==t[rs].lc) t[x].num=t[ls].num+t[rs].num-1;
else t[x].num=t[ls].num+t[rs].num;
}
void build(int x,int l,int r)
{
t[x].l=l,t[x].r=r;
if(l==r){
t[x].lc=t[x].rc=dis[rnk[l]];
t[x].num=1;
return;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushUp(x);
return;
}
inline void pushDown(int x)
{
if(t[x].tag){
t[ls].tag=t[rs].tag=t[x].tag;
t[ls].lc=t[ls].rc=t[x].tag;
t[ls].num=1;
t[rs].lc=t[rs].rc=t[x].tag;
t[rs].num=1;
t[x].tag=0;
}
}
void update(int x,int l,int r,int num)
{
if(t[x].l >= l&&t[x].r <= r){
t[x].lc=t[x].rc=num;
t[x].num=1;
t[x].tag=num;
return;
}
pushDown(x);
int mid=t[x].l+t[x].r>>1;
if(mid >= l) update(ls,l,r,num);
if(mid < r) update(rs,l,r,num);
pushUp(x);
return;
}
int getNum(int x,int l,int r)
{
if(t[x].l>=l&&t[x].r<=r){
if(tlc==0){
tlc=t[x].lc,trc=t[x].rc;
return t[x].num;
}
else if(trc != t[x].lc){
trc=t[x].rc;return t[x].num;
}
else if(trc==t[x].lc){
trc=t[x].rc;return t[x].num-1;
}
}
pushDown(x);
int mid=t[x].l+t[x].r>>1,ans=0;
if(mid >= l) ans+=getNum(ls,l,r);
if(mid < r) ans+=getNum(rs,l,r);
return ans;
}
}
void dfs1(int x,int f)
{
siz[x]=1;
for(int i = E.Head[x];i;i=E.Next[i]){
int y=E.Ver[i];
if(y==f) continue;
fa[y]=x;
dep[y]=dep[x]+1;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]) son[x]=y;
}
}
void dfs2(int x,int t)
{
top[x]=t;
dfn[x]=++tot;
rnk[tot]=x;
if(!son[x])return;
dfs2(son[x],t);
for(int i = E.Head[x];i;i=E.Next[i]){
int y=E.Ver[i];
if(y==fa[x]||y==son[x])continue;
dfs2(y,y);
}
}
inline void pathChange(int x,int y,int num)
{
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
lineTree::update(1,dfn[top[x]],dfn[x],num);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
lineTree::update(1,dfn[x],dfn[y],num);
return;
}
inline int pathNum(int x,int y)
{
int ans=0,lrc=0,llc=0;
while(top[x]!=top[y]){
tlc=0,trc=0;
if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(lrc,llc);
ans+=lineTree::getNum(1,dfn[top[x]],dfn[x]);
if(lrc==trc) ans-=1;
lrc=tlc;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y),swap(llc,lrc);
tlc=0,trc=0;
ans+=lineTree::getNum(1,dfn[x],dfn[y]);;
if(llc==trc) ans-=1;
if(lrc==tlc)ans-=1;
return ans;
}
inline int read(){
int num=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
num=(num<<1)+(num<<3)+(c^48);
c=getchar();
}
return num*f;
}
signed main(){
n=read(),m=read();
for(int i = 1;i <= n;i++) dis[i]=read();
for(int i = 1;i < n;i++){
int x=read(),y=read();
E.add(x,y);
E.add(y,x);
}
dfs1(1,0);
dfs2(1,1);
lineTree::build(1,1,n);
while(m--){
char c=getchar();
if(c=='C'){
int x=read(),y=read(),z=read();
pathChange(x,y,z);
}
else{
int x=read(),y=read();
printf("%lld\n",pathNum(x,y));
}
}
return 0;
}
测评记录:林克