#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const int INF = 0x3f3f3f3f;
vector<int> G[N];
int a[N];
ll val[N << 2], lazy[N << 2];
int fa[N], lo[N], ro[N], rnk[N], ck;
void dfs(int u) {
lo[u] = ++ck;
rnk[ck] = u;
for (auto v : G[u]) {
if (v == fa[u])continue;
fa[v] = u;
dfs(v);
}
ro[u] = ck;
}
void push_up(int u) {
val[u] = val[u << 1] | val[u << 1 | 1];
}
void push_down(int u) {
if (lazy[u]) {
val[u << 1] = lazy[u];
lazy[u << 1] = lazy[u];
val[u << 1 | 1] = lazy[u];
lazy[u << 1 | 1] = lazy[u];
lazy[u] = 0;
}
}
void build(int u, int l, int r) {
if (l == r) {
val[u] = (ll)1 << a[rnk[l]];
return;
}
int mid = l + r >> 1;
build(l << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
push_up(u);
}
void update(int u, int l, int r, int x, int y, int c) {
if (x <= l && r <= y) {
val[u] = (ll)1 << c;
lazy[u] = (ll)1 << c;
return;
}
int mid = l + r >> 1;
push_down(u);
if (x <= mid) {
update(u << 1, l, mid, x, y, c);
}
if (y > mid) {
update(u << 1 | 1, mid + 1, r, x, y, c);
}
push_up(u);
}
ll query(int u, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return val[u];
}
int mid = l + r >> 1;
push_down(u);
ll res = 0;
if (x <= mid) {
res |= query(u << 1, l, mid, x, y);
}
if (y > mid) {
res |= query(u << 1 | 1, mid + 1, r, x, y);
}
return res;
}
int main() {
int n, 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);
}
dfs(1);
build(1, 1, n);
while (m--) {
int o, x, y;
scanf("%d%d", &o, &x);
if (o == 1) {
scanf("%d", &y);
update(1, 1, n, lo[x], ro[x], y);
} else {
ll k = query(1, 1, n, lo[x], ro[x]);
int ans = 0;
while (k) {
if (k & 1) {
ans++;
}
k >>= 1;
}
printf("%d\n",ans);
}
}
return 0;
}