#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define REP(I,A,B) for(int I=A,END=B;I<=END;I++)
#define REPD(I,A,B) for(int I=A,END=B;I>=END;I--)
#define RI(X) scanf("%d",&X)
#define RS(X) scanf("%s",&X)
#define GCH getchar()
#define B(I) biao[I]
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define T(I) tree[I]
#define root (1)
#define MAXN 100005
struct adj
{
int y;
adj *next;
}*biao[MAXN]={0};
struct node
{
int son;//重儿子
int w; //点所在线段树の位置
int size; //大小
int deep; //深度
int fa; //父亲
int top; //链顶
}tree[MAXN]={{0}};
struct segment
{
int tot;//总颜色数
int lc; //左端点颜色
int rc; //右端点颜色
int lazy; //lazy
}st[MAXN<<2]={{0}};
using namespace std;
int color[MAXN]={0};
int n,m;
int id=0;
void open()
{
freopen("paint.in","r",stdin);
freopen("paint.out","w",stdout);
}
void close()
{
fclose(stdin);
fclose(stdout);
}
void add(int x,int y)
{
adj *p=(adj *)malloc(sizeof(adj));
p->y=y;
p->next=B(x);
B(x)=p;
}
/*
void dfs(int p)//son size deep fa
{
T(p).size=1;
T(p).deep=T(T(p).fa).deep+1;
for (adj *i=B(p);i!=NULL;i=i->next)
if (i->y!=T(p).fa)
{
T(i->y).fa=p;
dfs(i->y);
if (T(i->y).size>T(T(p).son).size)
T(p).son=i->y;
T(p).size+=T(i->y).size;
}
}*/
/*
这个应该改成BFS版本求son size deep fa
只要先搜一遍,在搜回去
*/
int queue[MAXN]={0};
inline void BFS()
{
int head,tail;
int i;
adj *j;
int x;
head=tail=1;
queue[head]=root;
T(root).deep=1;
T(root).fa=0;
T(root).size=1;
while (head<=tail)
{
i=queue[head];
head++;
for (j=B(i);j!=NULL;j=j->next)
{
x=j->y;
if (x!=T(i).fa)
{
tail++;
queue[tail]=x;
T(x).fa=i;
T(x).deep=T(i).deep+1;
T(x).size=1;
}
}
}
REPD(prime,tail,1)
{
i=queue[prime];
for (j=B(i);j!=NULL;j=j->next)
{
x=j->y;
if (x!=T(i).fa)
{
T(i).size+=T(x).size;
if (T(x).size>T(T(i).son).size) T(i).son=x;
}
}
}
}
inline void decomposition(int p)
{
int j;
adj *i;
T(p).w=++id;//记录位置
if (T(p).son!=0)
{
j=T(p).son;
T(j).top=T(p).top;
decomposition(j);
}
for (i=B(p);i!=NULL;i=i->next)
{
j=i->y;
if (j!=T(p).fa && j!=T(p).son)
{
T(j).top=j;
decomposition(j);
}
}
}
inline void down(int p)
{
int lch;
int rch;
if (st[p].lazy!=-1)
{
lch=p*2;
rch=p*2+1;
st[lch].lazy=st[rch].lazy=st[p].lazy;
st[lch].lc=st[lch].rc=st[rch].lc=st[rch].rc=st[p].lazy;
st[lch].tot=st[rch].tot=1;
st[p].lazy=-1;
}
}
inline void up(int p)
{
int lch=p*2;
int rch=p*2+1;
st[p].lc=st[lch].lc;
st[p].rc=st[rch].rc;
st[p].tot=st[lch].tot+st[rch].tot-(st[lch].rc==st[rch].lc);
}
inline segment query(int p,int l,int r,int ll,int rr)
{
if (ll==l && rr==r)
{
return st[p];
}
else
{
int mid=(l+r)/2;
down(p);
if (rr<=mid)
{
return query(p*2,l,mid,ll,rr);
}
else if (mid<ll)
{
return query(p*2+1,mid+1,r,ll,rr);
}
else
{
segment lch=query(p*2,l,mid,ll,mid);
segment rch=query(p*2+1,mid+1,r,mid+1,rr);
segment tmp;
tmp.lc=lch.lc;
tmp.rc=rch.rc;
tmp.tot=lch.tot+rch.tot-(lch.rc==rch.lc);
return tmp;
}
}
}
inline void update(int p,int l,int r,int ll,int rr,int value)
{
if (ll==l && rr==r)
{
st[p].lc=value;
st[p].rc=value;
st[p].tot=1;
st[p].lazy=value;//颜色lazy
}
else
{
int mid=(l+r)/2;
down(p);//先标记下传.
if (rr<=mid)
{
update(p*2,l,mid,ll,rr,value);
}
else if (mid<ll)
{
update(p*2+1,mid+1,r,ll,rr,value);
}
else
{
update(p*2,l,mid,ll,mid,value);
update(p*2+1,mid+1,r,mid+1,rr,value);
}
up(p);//修改p
}
}
inline void built_segment()
{
REP(i,1,n)
{
update(1,1,id,T(i).w,T(i).w,color[i]);
}
}
inline void init()
{
int x,y;
RI(n);
RI(m);
REP(i,1,n)
RI(color[i]);
REP(i,1,n-1)
{
RI(x);
RI(y);
add(x,y);
add(y,x);
}
T(root).fa=0;
BFS();
T(root).top=root;
id=0;
decomposition(root);
built_segment();
}
inline void paint(int u,int v,int color)
{
int fu=T(u).top,fv=T(v).top;
while(fu!=fv)
{
if (T(fu).deep<T(fv).deep)
{
swap(fu,fv);
swap(u,v);
}
update(1,1,id,T(fu).w,T(u).w,color);
u=T(fu).fa;
fu=T(u).top;
}
//写丑了这里可以和后面合并
if (u==v) //提到同一个位置了
{
update(1,1,id,T(u).w,T(u).w,color);
return ;
}
if (T(u).deep>T(v).deep)
{
swap(u,v);
}
update(1,1,id,T(u).w,T(v).w,color);
}
inline int find(int u,int v)
{
int fu=T(u).top,fv=T(v).top;
int ans=0,ulc=-1,vlc=-1;
segment tmp;
/*
开始逗比了,只记录了
一个左的位置。。没有发现是两个点一起向上走么
*/
while (fu!=fv)
{
if(T(fu).deep<T(fv).deep)
{
swap(fu,fv);
swap(u,v);
swap(ulc,vlc);
}
tmp=query(1,1,id,T(fu).w,T(u).w);
ans+=tmp.tot-(tmp.rc==ulc);
ulc=tmp.lc;
u=T(fu).fa;
fu=T(u).top;
}
//跪跪的发现一点,反正 u==y也要修改
if (T(u).deep>T(v).deep)
{
swap(u,v);
swap(ulc,vlc);
}
tmp=query(1,1,id,T(u).w,T(v).w);
//这一段真心奇葩 ulc与 tmp.lc相交 vlc与tmp.rc
ans+=tmp.tot-(ulc==tmp.lc)-(vlc==tmp.rc);
return ans;
}
inline void work()
{
char way;
int a,b,c;
GCH;
REP(i,1,m)
{
way=GCH;
if (way=='C')
{
RI(a);
RI(b);
RI(c);
GCH;
paint(a,b,c);
}
else
{
RI(a);
RI(b);
GCH;
printf("%d\n",find(a,b));
}
}
}
int main()
{
open();
init();
work();
close();
return 0;
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxjc3RyaW5nPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojZGVmaW5lIFJFUChJLEEsQikgZm9yKGludCBJPUEsRU5EPUI7STw9RU5EO0krKykKI2RlZmluZSBSRVBEKEksQSxCKSBmb3IoaW50IEk9QSxFTkQ9QjtJPj1FTkQ7SS0tKQojZGVmaW5lIFJJKFgpIHNjYW5mKCIlZCIsJlgpCiNkZWZpbmUgUlMoWCkgc2NhbmYoIiVzIiwmWCkKI2RlZmluZSBHQ0ggZ2V0Y2hhcigpCiNkZWZpbmUgQihJKSBiaWFvW0ldIAojZGVmaW5lIGRlYnVnKC4uLikgZnByaW50ZihzdGRlcnIsX19WQV9BUkdTX18pCiNkZWZpbmUgVChJKSB0cmVlW0ldCiNkZWZpbmUgcm9vdCAoMSkKI2RlZmluZSBNQVhOIDEwMDAwNQpzdHJ1Y3QgYWRqCnsKCQogIGludCB5OwogIGFkaiAqbmV4dDsKfSpiaWFvW01BWE5dPXswfTsKc3RydWN0IG5vZGUKewogIGludCBzb247Ly/ph43lhL/lrZAKICBpbnQgdzsgLy/ngrnmiYDlnKjnur/mrrXmoJHjga7kvY3nva4gCiAgaW50IHNpemU7IC8v5aSn5bCPIAogIGludCBkZWVwOyAvL+a3seW6piAKICBpbnQgZmE7ICAvL+eItuS6siAKICBpbnQgdG9wOyAvL+mTvumhtiAKfXRyZWVbTUFYTl09e3swfX07CnN0cnVjdCBzZWdtZW50CnsKICBpbnQgdG90Oy8v5oC76aKc6Imy5pWwCiAgaW50IGxjOyAvL+W3puerr+eCueminOiJsgogIGludCByYzsgLy/lj7Pnq6/ngrnpopzoibIgCiAgaW50IGxhenk7IC8vbGF6eQp9c3RbTUFYTjw8Ml09e3swfX07CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CmludCBjb2xvcltNQVhOXT17MH07CmludCBuLG07CmludCBpZD0wOwp2b2lkIG9wZW4oKQp7CiAgZnJlb3BlbigicGFpbnQuaW4iLCJyIixzdGRpbik7CiAgZnJlb3BlbigicGFpbnQub3V0IiwidyIsc3Rkb3V0KTsKfQp2b2lkIGNsb3NlKCkKewogIGZjbG9zZShzdGRpbik7CiAgZmNsb3NlKHN0ZG91dCk7Cn0Kdm9pZCBhZGQoaW50IHgsaW50IHkpCnsKICBhZGogKnA9KGFkaiAqKW1hbGxvYyhzaXplb2YoYWRqKSk7CiAgcC0+eT15OwogIHAtPm5leHQ9Qih4KTsKICBCKHgpPXA7Cn0KLyoKdm9pZCBkZnMoaW50IHApLy9zb24gc2l6ZSBkZWVwIGZhIAp7CiAgVChwKS5zaXplPTE7CiAgVChwKS5kZWVwPVQoVChwKS5mYSkuZGVlcCsxOwogIGZvciAoYWRqICppPUIocCk7aSE9TlVMTDtpPWktPm5leHQpCiAgICBpZiAoaS0+eSE9VChwKS5mYSkKICAgIHsKCSAgVChpLT55KS5mYT1wOwoJICBkZnMoaS0+eSk7CgkgIGlmIChUKGktPnkpLnNpemU+VChUKHApLnNvbikuc2l6ZSkKCSAgICBUKHApLnNvbj1pLT55OwoJICBUKHApLnNpemUrPVQoaS0+eSkuc2l6ZTsKCX0KfSovCi8qCui/meS4quW6lOivpeaUueaIkEJGU+eJiOacrOaxgnNvbiBzaXplIGRlZXAgZmEgCuWPquimgeWFiOaQnOS4gOmBje+8jOWcqOaQnOWbnuWOuyAKKi8KaW50IHF1ZXVlW01BWE5dPXswfTsKaW5saW5lIHZvaWQgQkZTKCkKewogIGludCBoZWFkLHRhaWw7CiAgaW50IGk7CiAgYWRqICpqOwogIGludCB4OwogIGhlYWQ9dGFpbD0xOwogIHF1ZXVlW2hlYWRdPXJvb3Q7CiAgVChyb290KS5kZWVwPTE7CiAgVChyb290KS5mYT0wOwogIFQocm9vdCkuc2l6ZT0xOwogIHdoaWxlIChoZWFkPD10YWlsKQogIHsKICAgIGk9cXVldWVbaGVhZF07CiAgICBoZWFkKys7CiAgICBmb3IgKGo9QihpKTtqIT1OVUxMO2o9ai0+bmV4dCkgCiAgICB7CiAgICAgIHg9ai0+eTsKICAgICAgaWYgKHghPVQoaSkuZmEpCiAgICAgIHsKICAgICAgCXRhaWwrKzsKCSAgICBxdWV1ZVt0YWlsXT14OwoJICAgIFQoeCkuZmE9aTsKCSAgICBUKHgpLmRlZXA9VChpKS5kZWVwKzE7CgkgICAgVCh4KS5zaXplPTE7CgkgIH0KICAgIH0KICB9CiAgUkVQRChwcmltZSx0YWlsLDEpCiAgewogICAgaT1xdWV1ZVtwcmltZV07CiAgICBmb3IgKGo9QihpKTtqIT1OVUxMO2o9ai0+bmV4dCkKICAgIHsKCSAgeD1qLT55OwoJICBpZiAoeCE9VChpKS5mYSkKCSAgewoJICAgIFQoaSkuc2l6ZSs9VCh4KS5zaXplOwoJICAgIGlmIChUKHgpLnNpemU+VChUKGkpLnNvbikuc2l6ZSkgVChpKS5zb249eDsKCSAgfQoJfQogIH0KfQppbmxpbmUgdm9pZCBkZWNvbXBvc2l0aW9uKGludCBwKQp7CiAgaW50IGo7CiAgYWRqICppOwogIFQocCkudz0rK2lkOy8v6K6w5b2V5L2N572uCiAgaWYgKFQocCkuc29uIT0wKQogIHsKICAJaj1UKHApLnNvbjsKICAJVChqKS50b3A9VChwKS50b3A7CiAgICBkZWNvbXBvc2l0aW9uKGopOwogIH0gCiAgZm9yIChpPUIocCk7aSE9TlVMTDtpPWktPm5leHQpCiAgewogICAgaj1pLT55OwogICAgaWYgKGohPVQocCkuZmEgJiYgaiE9VChwKS5zb24pCiAgICB7CgkgIFQoaikudG9wPWo7CgkgIGRlY29tcG9zaXRpb24oaik7Cgl9CiAgfQp9CmlubGluZSB2b2lkIGRvd24oaW50IHApCnsKICBpbnQgbGNoOwogIGludCByY2g7CiAgaWYgKHN0W3BdLmxhenkhPS0xKQogIHsKICAJbGNoPXAqMjsKICAJcmNoPXAqMisxOwogICAgc3RbbGNoXS5sYXp5PXN0W3JjaF0ubGF6eT1zdFtwXS5sYXp5OwogICAgc3RbbGNoXS5sYz1zdFtsY2hdLnJjPXN0W3JjaF0ubGM9c3RbcmNoXS5yYz1zdFtwXS5sYXp5OwogICAgc3RbbGNoXS50b3Q9c3RbcmNoXS50b3Q9MTsKICAgIHN0W3BdLmxhenk9LTE7CiAgfQp9CmlubGluZSB2b2lkIHVwKGludCBwKQp7CiAgaW50IGxjaD1wKjI7CiAgaW50IHJjaD1wKjIrMTsKICBzdFtwXS5sYz1zdFtsY2hdLmxjOwogIHN0W3BdLnJjPXN0W3JjaF0ucmM7CiAgc3RbcF0udG90PXN0W2xjaF0udG90K3N0W3JjaF0udG90LShzdFtsY2hdLnJjPT1zdFtyY2hdLmxjKTsKfQppbmxpbmUgc2VnbWVudCBxdWVyeShpbnQgcCxpbnQgbCxpbnQgcixpbnQgbGwsaW50IHJyKQp7CiAgaWYgKGxsPT1sICYmIHJyPT1yKQogIHsKICAgIHJldHVybiBzdFtwXTsKICB9CiAgZWxzZQogIHsKICAgIGludCBtaWQ9KGwrcikvMjsKICAgIGRvd24ocCk7CiAgICBpZiAocnI8PW1pZCkKICAgIHsKCSAgcmV0dXJuIHF1ZXJ5KHAqMixsLG1pZCxsbCxycik7Cgl9CgllbHNlIGlmIChtaWQ8bGwpCgl7CgkgIHJldHVybiBxdWVyeShwKjIrMSxtaWQrMSxyLGxsLHJyKTsKCX0KCWVsc2UgCgl7CgkgIHNlZ21lbnQgbGNoPXF1ZXJ5KHAqMixsLG1pZCxsbCxtaWQpOwoJICBzZWdtZW50IHJjaD1xdWVyeShwKjIrMSxtaWQrMSxyLG1pZCsxLHJyKTsKCSAgc2VnbWVudCB0bXA7CgkgIHRtcC5sYz1sY2gubGM7CgkgIHRtcC5yYz1yY2gucmM7CgkgIHRtcC50b3Q9bGNoLnRvdCtyY2gudG90LShsY2gucmM9PXJjaC5sYyk7CgkgIHJldHVybiB0bXA7Cgl9CiAgfQp9CmlubGluZSB2b2lkIHVwZGF0ZShpbnQgcCxpbnQgbCxpbnQgcixpbnQgbGwsaW50IHJyLGludCB2YWx1ZSkKewogIGlmIChsbD09bCAmJiBycj09cikKICB7CiAgICBzdFtwXS5sYz12YWx1ZTsKICAgIHN0W3BdLnJjPXZhbHVlOwogICAgc3RbcF0udG90PTE7CiAgICBzdFtwXS5sYXp5PXZhbHVlOy8v6aKc6ImybGF6eSAKICB9CiAgZWxzZQogIHsKICAgIGludCBtaWQ9KGwrcikvMjsKICAgIGRvd24ocCk7Ly/lhYjmoIforrDkuIvkvKAuIAogICAgaWYgKHJyPD1taWQpCiAgICB7CgkgIHVwZGF0ZShwKjIsbCxtaWQsbGwscnIsdmFsdWUpOwoJfQoJZWxzZSBpZiAobWlkPGxsKQoJewoJICB1cGRhdGUocCoyKzEsbWlkKzEscixsbCxycix2YWx1ZSk7Cgl9CgllbHNlIAoJewoJICB1cGRhdGUocCoyLGwsbWlkLGxsLG1pZCx2YWx1ZSk7CgkgIHVwZGF0ZShwKjIrMSxtaWQrMSxyLG1pZCsxLHJyLHZhbHVlKTsKCX0KCXVwKHApOy8v5L+u5pS5cCAKICB9Cn0KaW5saW5lIHZvaWQgYnVpbHRfc2VnbWVudCgpCnsKICBSRVAoaSwxLG4pCiAgewogICAgdXBkYXRlKDEsMSxpZCxUKGkpLncsVChpKS53LGNvbG9yW2ldKTsgCiAgfQp9CmlubGluZSB2b2lkIGluaXQoKQp7CiAgaW50IHgseTsKICBSSShuKTsKICBSSShtKTsKICBSRVAoaSwxLG4pCiAgICBSSShjb2xvcltpXSk7CiAgUkVQKGksMSxuLTEpCiAgewogICAgUkkoeCk7CiAgICBSSSh5KTsKICAgIGFkZCh4LHkpOwogICAgYWRkKHkseCk7CiAgfQogIFQocm9vdCkuZmE9MDsKICBCRlMoKTsKICBUKHJvb3QpLnRvcD1yb290OwogIGlkPTA7CiAgZGVjb21wb3NpdGlvbihyb290KTsKICBidWlsdF9zZWdtZW50KCk7IAp9CmlubGluZSB2b2lkIHBhaW50KGludCB1LGludCB2LGludCBjb2xvcikKewogIGludCBmdT1UKHUpLnRvcCxmdj1UKHYpLnRvcDsKICB3aGlsZShmdSE9ZnYpCiAgewogICAgaWYgKFQoZnUpLmRlZXA8VChmdikuZGVlcCkKICAgIHsKCSAgc3dhcChmdSxmdik7CgkgIHN3YXAodSx2KTsKCX0KCXVwZGF0ZSgxLDEsaWQsVChmdSkudyxUKHUpLncsY29sb3IpOwoJdT1UKGZ1KS5mYTsKCWZ1PVQodSkudG9wOwogIH0KICAvL+WGmeS4keS6hui/memHjOWPr+S7peWSjOWQjumdouWQiOW5tiAKICBpZiAodT09dikgLy/mj5DliLDlkIzkuIDkuKrkvY3nva7kuoYgCiAgewogICAgdXBkYXRlKDEsMSxpZCxUKHUpLncsVCh1KS53LGNvbG9yKTsKICAgIHJldHVybiA7CiAgfQogIGlmIChUKHUpLmRlZXA+VCh2KS5kZWVwKQogIHsKICAgIHN3YXAodSx2KTsKICB9CiAgdXBkYXRlKDEsMSxpZCxUKHUpLncsVCh2KS53LGNvbG9yKTsKfQppbmxpbmUgaW50IGZpbmQoaW50IHUsaW50IHYpCnsKICBpbnQgZnU9VCh1KS50b3AsZnY9VCh2KS50b3A7CiAgaW50IGFucz0wLHVsYz0tMSx2bGM9LTE7CiAgc2VnbWVudCB0bXA7CiAgLyoKICAgIOW8gOWni+mAl+avlOS6hu+8jOWPquiusOW9leS6hgogICAg5LiA5Liq5bem55qE5L2N572u44CC44CC5rKh5pyJ5Y+R546w5piv5Lik5Liq54K55LiA6LW35ZCR5LiK6LWw5LmIIAogICovCQkgCiAgd2hpbGUgKGZ1IT1mdikKICB7CiAgICBpZihUKGZ1KS5kZWVwPFQoZnYpLmRlZXApCiAgICB7CgkgIHN3YXAoZnUsZnYpOwoJICBzd2FwKHUsdik7CgkgIHN3YXAodWxjLHZsYyk7Cgl9Cgl0bXA9cXVlcnkoMSwxLGlkLFQoZnUpLncsVCh1KS53KTsKCWFucys9dG1wLnRvdC0odG1wLnJjPT11bGMpOwoJdWxjPXRtcC5sYzsKCXU9VChmdSkuZmE7CglmdT1UKHUpLnRvcDsKICB9CiAgLy/ot6rot6rnmoTlj5HnjrDkuIDngrnvvIzlj43mraMgdT09eeS5n+imgeS/ruaUuSAKICBpZiAoVCh1KS5kZWVwPlQodikuZGVlcCkKICB7CiAgICBzd2FwKHUsdik7CiAgICBzd2FwKHVsYyx2bGMpOwogIH0KICB0bXA9cXVlcnkoMSwxLGlkLFQodSkudyxUKHYpLncpOwogIC8v6L+Z5LiA5q6155yf5b+D5aWH6JGpIHVsY+S4jiB0bXAubGPnm7jkuqQgdmxj5LiOdG1wLnJjCiAgYW5zKz10bXAudG90LSh1bGM9PXRtcC5sYyktKHZsYz09dG1wLnJjKTsKICByZXR1cm4gYW5zOwp9CmlubGluZSB2b2lkIHdvcmsoKQp7CiAgY2hhciB3YXk7CiAgaW50IGEsYixjOwogIEdDSDsKICBSRVAoaSwxLG0pCiAgewogIAl3YXk9R0NIOwogIAlpZiAod2F5PT0nQycpCiAgCXsKICAJICBSSShhKTsKICAJICBSSShiKTsKICAJICBSSShjKTsKICAJICBHQ0g7IAogICAgICBwYWludChhLGIsYyk7IAogICAgfQogICAgZWxzZSAKICAgIHsKCSAgUkkoYSk7CgkgIFJJKGIpOwoJICBHQ0g7CgkgIHByaW50ZigiJWRcbiIsZmluZChhLGIpKTsKCX0KICB9Cn0KaW50IG1haW4oKQp7CiAgb3BlbigpOwogIGluaXQoKTsKICB3b3JrKCk7CiAgY2xvc2UoKTsKICByZXR1cm4gMDsKfQ==