![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int M=3e5+5; struct node{ int l,r,cnt,lazy; node(int l1=0,int r1=0,int cnt1=0,int lazy1=0):l(l1),r(r1),cnt(cnt1),lazy(lazy1){} }tree[M<<2]; int fa[M],sz[M],deep[M],dfn[M],son[M],to[M],a[M],top[M],cnt,n; char s[2]; vector<int>g[M]; void dfs1(int u,int from){ fa[u]=from; sz[u]=1; deep[u]=deep[from]+1; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(v!=from){ dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } } void dfs2(int u,int t){ top[u]=t; dfn[u]=++cnt; to[cnt]=u; if(!son[u]) return ; dfs2(son[u],t); for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } void up(int root){ tree[root].cnt=tree[root<<1].cnt+tree[root<<1|1].cnt; if(tree[root<<1].r==tree[root<<1|1].l) tree[root].cnt--; tree[root].l=tree[root<<1].l; tree[root].r=tree[root<<1|1].r; } void build(int root,int l,int r){ tree[root].lazy=0; if(l==r){ tree[root].l=tree[root].r=a[to[l]]; tree[root].cnt=1; return ; } int midd=(l+r)>>1; build(root<<1,l,midd); build(root<<1|1,midd+1,r); up(root); } void pushdown(int root){ tree[root<<1]=tree[root<<1|1]=node(tree[root].l,tree[root].r,1,tree[root].lazy); tree[root].lazy=0; } void update(int L,int R,int x,int root,int l,int r){ if(L<=l&&r<=R){ tree[root]=node(x,x,1,x); return ; } if(tree[root].lazy) pushdown(root); int midd=(l+r)>>1; if(L<=midd) update(L,R,x,root<<1,l,midd); if(R>midd) update(L,R,x,root<<1|1,midd+1,r); up(root); } void add(int u,int v ,int w){ int fu=top[u],fv=top[v]; while(fu!=fv){ if(deep[fu]>=deep[fv]) update(dfn[fu],dfn[u],w,1,1,n),u=fa[fu],fu=top[u]; else update(dfn[fv],dfn[v],w,1,1,n),v=fa[fv],fv=top[v]; } if(dfn[u]<=dfn[v]) update(dfn[u],dfn[v],w,1,1,n); else update(dfn[v],dfn[u],w,1,1,n); } node meger(node a,node b){ if(!a.cnt) return b; if(!b.cnt) return a; node ans=node(0,0,0,0); ans.cnt=a.cnt+b.cnt; if(a.r==b.l) ans.cnt--; ans.l=a.l; ans.r=b.r; return ans; } node query(int L,int R,int root,int l,int r){ if(L<=l&&r<=R){ return tree[root]; } if(tree[root].lazy) pushdown(root); int midd=(l+r)>>1; node ans; if(L<=midd) ans=query(L,R,root<<1,l,midd); if(R>midd) ans=meger(ans,query(L,R,root<<1|1,midd+1,r)); up(root); return ans; } int solve(int u,int v){ node l,r; int fv=top[v],fu=top[u]; while(fv!=fu){ if(deep[fu]>=deep[fv]) l=meger(query(dfn[fu],dfn[u],1,1,n),l),u=fa[fu],fu=top[u]; else r=meger(query(dfn[fv],dfn[v],1,1,n),r),v=fa[fv],fv=top[v]; } if(dfn[u]<=dfn[v]) r=meger(query(dfn[u],dfn[v],1,1,n),r); else l=meger(query(dfn[v],dfn[u],1,1,n),l); swap(l.l,l.r); l=meger(l,r); return l.cnt; } int main(){ int m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); }//cout<<"!!"<<endl; dfs1(1,1); dfs2(1,1); build(1,1,n); while(m--){ int u,v,w; scanf("%s",s); if(s[0]=='Q'){ scanf("%d%d",&u,&v); printf("%d ",solve(u,v)); } else{ scanf("%d%d%d",&u,&v,&w); add(u,v,w); } } return 0; }