#include <cstdio>
#include <iostream>
#include<cstring>
using namespace std;
#define N 300010
const int M=2e5+10;
const int INF=1<<30;
struct Node{
Node *p,*ch[2];
int rev;
int val,add;
int l,r;
int sz;
}node[N],*null;
int n_cnt;
void newnode(int w)
{
Node* cur=&node[n_cnt++];
cur->p=cur->ch[0]=cur->ch[1]=null;
cur->add=-1;
cur->val=cur->l=cur->r=w;
cur->rev=0;
cur->sz=1;
}
void init()
{
null=node;
null->p=null->ch[0]=null->ch[1]=null;
null->add=-1;
null->val=-1;null->l=null->r=-1;
null->sz=0;
null->rev=0;
n_cnt=1;
}
struct dynamictree
{
bool isroot(Node *x)//判根
{
return x->p==null || x->p->ch[0]!=x && x->p->ch[1]!=x;
}
void lazy(Node *x,int w)
{
x->add=x->val=x->l=x->r=w;x->sz=1;
}
void flip(Node *x)
{
x->rev^=1;
swap(x->ch[0],x->ch[1]);
swap(x->l,x->r);
}
void pushup(Node *x)
{
x->sz=1;
if(x->ch[0]!=null)
{
x->l=x->ch[0]->l;
x->sz+=x->ch[0]->sz;
if(x->val==x->ch[0]->r)
{
x->sz--;
}
}
else x->l=x->val;
if(x->ch[1]!=null)
{
x->r=x->ch[1]->r;
x->sz+=x->ch[1]->sz;
if(x->val==x->ch[1]->l)
{
x->sz--;
}
}
else x->r=x->val;
}
void pushdown(Node *x)
{
if(x==null) return;
if(x->add!=-1)
{
if(x->ch[0]!=null)lazy(x->ch[0],x->add);
if(x->ch[1]!=null)lazy(x->ch[1],x->add);
x->add=-1;
}
if(x->rev)
{
x->rev=0;
if(x->ch[0]!=null)flip(x->ch[0]);
if(x->ch[1]!=null)flip(x->ch[1]);
}
}
void rotate(Node *x,int f)
{
Node *y=x->p;
pushdown(y);pushdown(x);
y->ch[!f]=x->ch[f];
if(x->ch[f]!=null) x->ch[f]->p=y;
x->p=y->p;
if(!isroot(y))
{
y->p->ch[y==y->p->ch[1]]=x;
}
x->ch[f]=y;
y->p=x;
pushup(y);
}
//找到链的根
void splay(Node *x)
{
pushdown(x);
while (!isroot(x))
{
Node *y=x->p;
if(isroot(y)) rotate(x,x==y->ch[0]);
else
{
int f=y->p->ch[0]==y;
if(y->ch[f]==x) rotate(x,!f);
else rotate(y,f);
rotate(x,f);
}
}
pushup(x);
}
///找到所在树的树根
Node *access(Node *u)
{
Node *v=null;
while (u!=null)
{
splay(u);
u->ch[1]=v;
pushup(u);
v=u;
u=u->p;
}
return v;
}
Node *link(Node *u,Node *v)//合并
{
access(u);
splay(u);
flip(u);
u->p=v;
}
void makeroot(Node *x)//换根
{
access(x);
splay(x);
flip(x);
}
Node *getroot(Node *x)//找根
{
access(x);
splay(x);
while(x->ch[0]!=null)x=x->ch[0];
return x;
}
bool queryuv(Node *u,Node *v)//判断是否在同一子树
{
while (u->p!=null) u=u->p;
while (v->p!=null) v=v->p;
return u==v;
}
void dfs(Node *x)
{
if(x==null)return ;
pushdown(x);
dfs(x->ch[0]);
printf("%d ",x->val);
dfs(x->ch[1]);
}
}spt;
int n,m,u,v,w;
char ss[20];
int main ()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
int a;scanf("%d",&a);
newnode(a);
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
spt.link(node+u,node+v);
}
for(int i=1;i<=m;i++)
{
scanf("%s",ss);
if(ss[0]=='Q')
{
int a,b;scanf("%d%d",&a,&b);
spt.makeroot(node+a);
spt.access(node+b);
spt.splay(node+b);
printf("%d-%d\n",i-1,node[b].sz);
}
else
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
spt.makeroot(node+a);
spt.access(node+b);
spt.splay(node+b);
spt.lazy(node+b,c);
}
}
}
return 0;
}