#include<cstdio>
#include<iostream>
#include<cctype>
using namespace std;
//常用函数
const int MAXN=1e5+10;
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
#define t tree[pos]
#define tl tree[ls(pos)]
#define tr tree[rs(pos)]
//结构体
struct edge
{
int nxt,v;
}e[2*MAXN];
struct lineCutTree
{
int l,r;
int leftColour,RightColour,colourNumber,lazyColour;
}tree[4*MAXN];
//定义
int n,m;
int head[2*MAXN],a[MAXN],f[MAXN],size[MAXN],dep[MAXN],son[MAXN],rk[MAXN],id[MAXN],cnt,num,top[MAXN];
void add(int u,int v)
{
cnt++;
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
//树链剖分
void dfs1(int u,int fa)
{
dep[u] = dep[fa]+1;
size[u] = 1;
f[u] = fa;
for(int i = head[u]; i ; i= e[i].nxt)
{
int v = e[i].v;
if(v == fa)continue;
dfs1(v,u);
size[u] += size[v];
if(size[v] > size[son[u]] || !son[u])
{
son[u] = v;
}
}
}
void dfs2(int u,int fa,int tp)
{
num++;
id[u] = num;
rk[num] = u;
top[u] = tp;
if(!son[u])return;
dfs2(son[u],u,tp);
for(int i=head[u];i;i=e[i].nxt)
{
int v = e[i].v;
if(v == son[u] || v==fa) continue;
dfs2(v,u,v);
}
}
//线段树
void build(int pos,int l,int r);
lineCutTree query(int pos,int l,int r);
void change(int pos,int l,int r,int w);
void update(int pos);
//lca
int find(int x,int y)
{
int ret=0;
int pos1=0,pos2=0;
int fx=top[x],fy=top[y];
while(fx != fy)
{
if(dep[fx] > dep[fy])
{
lineCutTree temp = query(1,id[fx],id[x]);
ret += temp.colourNumber;
if(temp.RightColour == pos1) ret--;
pos1 = temp.leftColour;
x = f[fx];
fx = top[x];
}else
{
lineCutTree temp =query(1,id[fy],id[y]);
ret += temp.colourNumber;
if(temp.RightColour == pos2)ret--;
pos2 = temp.leftColour;
y = f[fy];
fy = top[y];
}
}
if(id[x] > id[y])
{
swap(x,y);
swap(pos1,pos2);
}
lineCutTree temp = query(1,id[x],id[y]);
ret += temp.colourNumber;
if(temp.leftColour == pos1) ret--;
if(temp.RightColour == pos2)ret--;
return ret;
}
void update(int x,int y,int w)
{
int fx=top[x],fy=top[y];
while(fx != fy)
{
if(dep[fx] > dep[fy])
{
change(1,id[fx],id[x],w);
x = f[fx];
fx = top[x];
}else
{
change(1,id[fy],id[y],w);
y = f[fy];
fy = top[y];
}
}
if(id[x] > id[y])swap(x,y);
change(1,id[x],id[y],w);
}
//运行
void solve();
int main()
{
solve();
return 0;
}
//函数 运行
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
add(u,v);add(v,u);
}
dfs1(1,0);
dfs2(1,0,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
char op;
cin>>op;
if(op=='C')
{
int a,b,c;
cin>>a>>b>>c;
update(a,b,c);
}else if(op=='Q')
{
int a,b;
cin>>a>>b;
cout<<find(a,b)<<endl;
}
}
}
void build(int pos,int l,int r)
{
int mid = (l+r) >> 1;
tree[pos].l=l;
tree[pos].r=r;
if(tree[pos].l==tree[pos].r)
{
tree[pos].leftColour = tree[pos].RightColour = a[rk[mid]];
tree[pos].colourNumber = 1;
return;
}
build(ls(pos),l,mid);
build(rs(pos),mid+1,r);
tree[pos].colourNumber = tree[ls(pos)].colourNumber + tree[rs(pos)].colourNumber;
tree[pos].leftColour = tree[ls(pos)].leftColour;
tree[pos].RightColour = tree[rs(pos)].RightColour;
if(tree[ls(pos)].RightColour == tree[rs(pos)].leftColour)
{
tree[pos].colourNumber --;
}
}
void change(int pos,int l,int r,int w)
{
int mid = (tree[pos].l + tree[pos].r) >> 1;
if(tree[pos].l >= l && tree[pos].r <= r)
{
tree[pos].lazyColour = w;
tree[pos].leftColour = w;
tree[pos].RightColour = w;
tree[pos].colourNumber = 1;
return;
}
update(pos);
if(l <= mid)
{
change(ls(pos),l,r,w);
}
if(r > mid)
{
change(rs(pos),l,r,w);
}
tree[pos].colourNumber = tree[ls(pos)].colourNumber + tree[rs(pos)].colourNumber;
tree[pos].leftColour = tree[ls(pos)].leftColour;
tree[pos].RightColour = tree[rs(pos)].RightColour;
if(tree[ls(pos)].RightColour == tree[rs(pos)].leftColour)
{
tree[pos].colourNumber -- ;
}
}
void update(int pos)
{
if(tree[pos].lazyColour)
{
tree[ls(pos)].leftColour = tree[pos].lazyColour;
tree[ls(pos)].RightColour = tree[pos].lazyColour;
tree[ls(pos)].colourNumber = 1;
tree[rs(pos)].leftColour = tree[pos].lazyColour;
tree[rs(pos)].RightColour = tree[pos].lazyColour;
tree[rs(pos)].colourNumber = 1;
}
if(tree[pos].l != tree[pos].r)
{
tree[ls(pos)].lazyColour = tree[pos].lazyColour;
tree[rs(pos)].lazyColour = tree[pos].lazyColour;
}
tree[pos].lazyColour = 0;
}
lineCutTree query(int pos ,int l ,int r)
{
int mid = ( tree[pos].l + tree[pos].r ) >> 1;
if(tree[pos].l >= l && tree[pos].r <= r)
{
return t;
}
update(pos);
lineCutTree temp,tempLeft,tempRight;
temp.leftColour = 0;
temp.RightColour = 0;
temp.colourNumber = 0;
if(l <= mid)
{
tempLeft = query (ls(pos) , l , r);
temp.leftColour = tempLeft.leftColour;
temp.colourNumber += tempLeft.colourNumber;
}
if(r > mid)
{
tempRight = query (rs(pos) , l , r);
temp.RightColour = tempRight.RightColour;
temp.colourNumber += tempRight.colourNumber;
}
if(!temp.leftColour) return tempRight;
if(!temp.RightColour) return tempLeft;
if(tempLeft.RightColour == tempRight.leftColour)temp.colourNumber --;
return temp;
}
WA自动机