#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=400005;
struct edge
{
ll from;
ll to;
ll next;
}e[N];
ll head[N];
ll tot=0,tim=0;
ll in[N],out[N],pos[N];
void add_edge(ll u,ll v)
{
tot++;
e[tot].from=u;
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot;
}
void dfs(ll x,ll fa)
{
in[x]=++tim;
pos[tim]=x;
for(int i=head[x];i;i=e[i].next)
{
ll y=e[i].to;
if(y==fa)
continue;
dfs(y,x);
}
out[x]=tim;
}
ll L[4*N],R[4*N],ans[4*N],lazy[4*N];
ll c[N];
void push_up(ll rt)
{
ans[rt]=ans[rt<<1]|ans[rt<<1|1];
}
void push_down(ll rt)
{
if(lazy[rt])
{
ans[rt<<1]=lazy[rt];
ans[rt<<1|1]=lazy[rt];
lazy[rt<<1]=lazy[rt];
lazy[rt<<1|1]=lazy[rt];
lazy[rt]=0;
}
}
void build(int p,int l,int r)
{
L[p]=l,R[p]=r;
if(l==r)
{
ans[p]=c[pos[l]];
return;
}
int mid=(l+r)/2;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
push_up(p);
}
void update(int p,int l,int r,int colour)
{
if(r<L[p]||l>R[p])
return;
if(l<=L[p]&&r>=R[p])
{
ans[p]=(1ll<<(colour-1));
lazy[p]=ans[p];
}
push_down(p);
update(p<<1,l,r,colour);
update(p<<1|1,l,r,colour);
push_up(p);
}
ll query(int p,int l,int r)
{
if(l<=L[p]&&r>=R[p])
{
return ans[p];
}
ll cnt=0;
int mid=(L[p]+R[p])>>1;
push_down(p);
if(l<=mid)cnt|=query(p<<1,l,r);
if(r>mid)cnt|=query(p<<1|1,l,r);
return cnt;
}
ll lowbit(ll x)
{
return x&(-x);
}
int num2(ll x)
{
int ans=0;
for(ll i=x;i>0;i-=lowbit(i))
ans++;
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
ll temp;
for(int i=1;i<=n;i++)
{
scanf("%lld",&temp);
c[i]=1ll<<(temp-1);
}
int u,v,colour;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int mark;
scanf("%d",&mark);
if(mark&1)
{
scanf("%d%d",&u,&colour);
update(1,in[u],out[u],colour);
}
else
{
scanf("%d",&u);
ll num=query(1,in[u],out[u]);
printf("%d\n",num2(num));
}
}
system("pause");
}