#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
using namespace std;
const int N = 500005;
int n, m, col[N], hed[N * 2], tal[N * 2], nxt[N * 2], cnt = 0, c[N], ll[N],
                                                      rr[N], opt = 0, k[N];
long long t[N * 8];
bool LZT[N * 8];
void push_down(int num) {
  if (!LZT[num]) return;
  LZT[num << 1] = 1, LZT[num << 1 | 1] = 1, t[num << 1] = t[num],
             t[num << 1 | 1] = t[num], LZT[num] = 0;
}
void addege(int x, int y) {
  ++cnt, tal[cnt] = y, nxt[cnt] = hed[x], hed[x] = cnt;
}
void dfs(int x, int father) {
  ++opt, ll[x] = opt, k[opt] = x;
  for (int i = hed[x]; i; i = nxt[i]) {
    int v = tal[i];
    if (v == father) continue;
    dfs(v, x);
  }
  rr[x] = opt;
}
void build(int l, int r, int num) {
  if (l == r) {
    t[num] = 1ll << col[k[l]], LZT[num] = 0;
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, num << 1);
  build(mid + 1, r, num << 1 | 1);
  t[num] = (t[num << 1] | t[num << 1 | 1]);
  LZT[num] = 0;
}
void add(int l, int r, int num, int L, int R, int C) {
  if (l >= L && r <= R) {
    LZT[num] = 1, t[num] = (1ll << C);
    return;
  }
  push_down(num);
  int mid = (l + r) >> 1;
  if (mid >= R)
    add(l, mid, num << 1, L, R, C);
  else if (mid < L)
    add(mid + 1, r, num << 1 | 1, L, R, C);
  else
    add(l, mid, num << 1, L, R, C), add(mid + 1, r, num << 1 | 1, L, R, C);
  t[num] = (t[num << 1] | t[num << 1 | 1]);
}
long long ask(int l, int r, int num, int L, int R) {
  if (l >= L && r <= R) return t[num];
  push_down(num);
  int mid = (l + r) >> 1;
  if (mid >= R) return ask(l, mid, num << 1, L, R);
  if (mid < L) return ask(mid + 1, r, num << 1 | 1, L, R);
  return ask(l, mid, num << 1, L, R) | ask(mid + 1, r, num << 1 | 1, L, R);
}
int nume(long long x) {
  int ans = 0;
  while (x) x -= (x & (-x)), ++ans;
  return ans;
}
int sol(int L, int R) { return nume(ask(1, n, 1, L, R)); }
int main() {
  scanf("%d%d", &n, &m);
  for (register int i = 1; i <= n; ++i) scanf("%d", &col[i]);
  for (register int i = 1; i < n; ++i) {
    int a, b;
    scanf("%d%d", &a, &b), addege(a, b), addege(b, a);
  }
  dfs(1, 0), n *= 2, build(1, n, 1);
  while (m--) {
    int opt, a, b;
    scanf("%d%d", &opt, &a);
    if (opt == 1) {
      int L = ll[a], R = rr[a];
      scanf("%d", &b), add(1, n, 1, L, R, b);
    } else {
      int L = ll[a], R = rr[a];
      printf("%d\n", sol(L, R));
    }
  }
  return 0;
}
