#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
namespace FAST_IO{
#define ll long long
#define ull unsigned long long
#define db double
#define _8 __int128_t
const int LEN=1<<20;
char BUF[LEN],PUF[LEN];
int Pin=LEN,Pout;
inline void flushin(){memcpy(BUF,BUF+Pin,LEN-Pin),fread(BUF+LEN-Pin,1,Pin,stdin),Pin=0;return;}
inline void flushout(){fwrite(PUF,1,Pout,stdout),Pout=0;return;}
inline char Getc(){return (Pin==LEN?(fread(BUF,1,LEN,stdin),Pin=0):0),BUF[Pin++];}
inline char Get(){return BUF[Pin++];}
inline void Putc(char x){if(Pout==LEN)flushout(),Pout=0;PUF[Pout++]=x;}
inline void Put(char x){PUF[Pout++]=x;}
template<typename tp=int>inline tp read(){(Pin+32>=LEN)?flushin():void();tp res=0;char f=1,ch=' ';for(;ch<'0'||ch>'9';ch=Get())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=Get())res=(res<<3)+(res<<1)+ch-48;return res*f;}
template<typename tp>inline void wt(tp a){if(a>9)wt(a/10);Put(a%10+'0');return;}
template<typename tp>inline void write(tp a,char b='\n')
{
static int stk[20],top;
(Pout+32>=LEN)?flushout():void();
if(a<0)Put('-'),a=-a;
else if(a==0)Put('0');
for(top=0;a;a/=10)stk[++top]=a%10;
for(;top;--top)Put(stk[top]^48);
Put(b);
return;
}
inline void wt_str(std::string s){for(char i:s)Putc(i);return;}
}
using namespace FAST_IO;
int col[400005], dfn[400005], tot, pre[400005], siz[400005];
bitset<63> tree[2000005], tag[2000005];
struct node{
int to, next;
}k[800005];
int head[800005], number;
void add(int x, int y) {
k[++number].next = head[x];
k[number].to = y;
head[x] = number;
}
void dfs(int x, int fa) {
dfn[x] = ++tot; pre[tot] = x; siz[x] = 1;
for(int i = head[x]; i; i = k[i].next) {
int to = k[i].to;
if(to == fa) continue;
dfs(to, x); siz[x] += siz[to];
}
}
inline void pushup(int cur) {
tree[cur] = tree[cur << 1] | tree[cur << 1 | 1];
}
void build(int cur, int l, int r) {
if(l == r) {
tree[cur].set(col[pre[l]]);
return;
}
int mid = (l + r) >> 1;
build(cur << 1, l, mid), build(cur << 1 | 1, mid + 1, r);
pushup(cur);
}
inline void addtag(int cur, int l, int r, int val) {
tree[cur].reset(), tag[cur].reset();
tree[cur].set(val); tag[cur].set(val);
}
inline void addtag(int cur, int l, int r, bitset<63> val) {
tree[cur] = val; tag[cur] = val;
}
inline void pushdown(int cur, int l, int r) {
if(!tag[cur].count()) return;
int mid = l + r >> 1;
addtag(cur << 1, l, mid, tag[cur]);
addtag(cur << 1 | 1, mid + 1, r, tag[cur]);
tag[cur].reset();
}
void update(int cur, int l, int r, int x, int y, int val) {
if(l >= x and r <= y) {
addtag(cur, l, r, val);
return;
}
int mid = l + r >> 1; pushdown(cur, l, r);
if(x <= mid) update(cur << 1, l, mid, x, y, val);
if(y > mid) update(cur << 1 | 1, mid + 1, r, x, y, val);
pushup(cur);
}
bitset<63> ask(int cur, int l, int r, int x, int y) {
if(l == r) return tree[cur];
int mid = l + r >> 1; bitset<63> ans; ans.reset(); pushdown(cur, l, r);
if(x <= mid) ans |= ask(cur << 1, l, mid, x, y);
if(y > mid) ans |= ask(cur << 1 | 1, mid + 1, r, x, y);
return ans;
}
int main() {
int n = read(), m = read();
for(int i = 1; i <= n; i++) col[i] = read();
for(int i = 1; i <= n - 1; i++) {
int x, y; x = read(), y = read();
add(x, y), add(y, x);
}
dfs(1, 0); build(1, 1, n);
while(m--) {
int opt, u, v; opt = read(), u = read();
if(opt == 1) {
v = read();
update(1, 1, n, dfn[u], dfn[u] + siz[u] - 1, v);
}
else write(ask(1, 1, n, dfn[u], dfn[u] + siz[u] - 1).count(), '\n');
}
flushout();
}