#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
const int maxn=4e5+100;
//线段树+状压
//线段树的权值表示区间颜色的出现次数
typedef long long ll;
vector<int> g[maxn];
ll c[maxn<<2],lz[maxn<<2];
int a[maxn];
int w[maxn];
int n,q;
int dfn[maxn],tot,sz[maxn];
void dfs (int x,int pre) {
dfn[x]=++tot;
w[tot]=a[x];
sz[x]=1;
for (int y:g[x]) if (y!=pre) dfs(y,x),sz[x]+=sz[y];
}
void pushup (int i) {
c[i]=(c[i<<1]|c[i<<1|1]);
}
void pushdown (int i) {
if (lz[i]) {
c[i<<1]=lz[i];
lz[i<<1]=lz[i];
c[i<<1|1]=lz[i];
lz[i<<1|1]=lz[i];
lz[i]=0;
}
}
void build (int i,int l,int r) {
if (l==r) {
c[i]=(1ll<<(w[l]-1));
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
pushup(i);
}
void up (int i,int l,int r,int L,int R,int x) {
if (l>=L&&r<=R) {
c[i]=(1ll<<(x-1));
lz[i]=(1ll<<(x-1));
return;
}
pushdown(i);
int mid=(l+r)>>1;
if (L<=mid) up(i<<1,l,mid,L,R,x);
if (R>mid) up(i<<1|1,mid+1,r,L,R,x);
pushup(i);
}
long long query (int i,int l,int r,int L,int R) {
if (l>=L&&r<=R) return c[i];
pushdown(i);
int mid=(l+r)>>1;
long long ans=0;
if (L<=mid) ans|=(query(i<<1,l,mid,L,R));
if (R>mid) ans|=(query(i<<1|1,mid+1,r,L,R));
return ans;
}
int main () {
n=read();q=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<n;i++) {
int x=read();
int y=read();
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,0);
build(1,1,n);
while (q--) {
int op=read();
if (op==1) {
int x=read();
int y=read();
up(1,1,n,dfn[x],dfn[x]+sz[x]-1,y);
}
else {
int x=read();
long long ans=query(1,1,n,dfn[x],dfn[x]+sz[x]-1);
int cnt=0;
for (int i=1;i<=60;i++) if (ans&(1ll<<(i-1))) cnt++;
printf("%d
",cnt);
}
}
}