#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template <class T>
inline bool Min(T &a, T b) {
  return a > b ? (a = b, true) : false;
}
template <class T>
inline bool Max(T &a, T b) {
  return a < b ? (a = b, true) : false;
}
inline int ni() {
  int a;
  scanf("%d", &a);
  return a;
}
inline void pi(int a) { printf("%d", a); }
inline ll nl() {
  ll a;
  scanf("%lld", &a);
  return a;
}
inline void pl(ll a) { printf("%lld", a); }
inline double nd() {
  double a;
  scanf("%lf", &a);
  return a;
}
inline void pd(double a) { printf("%.8lf", a); }
inline char nc() {
  char a;
  scanf("%c", &a);
  return a;
}
inline void pc(char a) { printf("%c", a); }
inline void ps(string str) { printf("%s", str.c_str()); }
inline void sp() { putchar(' '); }
inline void en() { putchar('\n'); }
const int N = 4e5 + 10;
const int M = 60;
const int SZ = 1 << 20;
const int START = 1;
const int FROM = 0;
const int TO = SZ - 1;
vector<int> gp[N];
ll maxi[SZ * 2];
bool def[SZ * 2];
int tin[N];
int tout[N];
int timer = 0;
inline void dfs(int v, int p) {
  tin[v] = timer++;
  for (int next : gp[v])
    if (next != p) dfs(next, v);
  tout[v] = timer++;
}
inline void update(int v) {
  if (!def[v]) maxi[v] = maxi[v << 1] | maxi[(v << 1) | 1];
}
inline void push(int v) {
  if (def[v]) {
    maxi[v << 1] = maxi[(v << 1) | 1] = maxi[v];
    def[v << 1] = def[(v << 1) | 1] = true;
    def[v] = false;
  }
}
inline void tree_set(int ql, int qr, ll val, int v = START, int l = FROM,
                     int r = TO) {
  if (qr < l or ql > r) return;
  if (ql <= l and r <= qr) {
    maxi[v] = val;
    def[v] = true;
    return;
  }
  push(v);
  int mid = (l + r) >> 1;
  tree_set(ql, qr, val, v << 1, l, mid);
  tree_set(ql, qr, val, (v << 1) | 1, mid + 1, r);
  update(v);
}
inline ll tree_get(int ql, int qr, int v = START, int l = FROM, int r = TO) {
  if (qr < l || ql > r) return 0;
  if (ql <= l and r <= qr) return maxi[v];
  push(v);
  int mid = (l + r) >> 1;
  return tree_get(ql, qr, v << 1, l, mid) |
         tree_get(ql, qr, (v << 1) | 1, mid + 1, r);
}
inline int get(int v) {
  int ans = 0;
  ll g = tree_get(tin[v], tout[v]);
  while (g) ans += g & 1, g >>= 1;
  return ans;
}
void solve() {
  int n, m, x, y;
  scanf("%d%d", &n, &m);
  vector<int> colors(n);
  vector<int> ans;
  for (int i = 0; i < (int)(n); ++i) scanf("%d", &colors[i]), --colors[i];
  for (int i = 0; i < (int)(n - 1); ++i) {
    scanf("%d%d", &x, &y);
    --x, --y;
    gp[x].push_back(y);
    gp[y].push_back(x);
  }
  dfs(0, 0);
  for (int i = 0; i < (int)(n); ++i) {
    tree_set(tin[i], tin[i], 1LL << colors[i]);
    tree_set(tout[i], tout[i], 1LL << colors[i]);
  }
  int t, v, c;
  for (int i = 0; i < (int)(m); ++i) {
    scanf("%d%d", &t, &v);
    if (t == 1) {
      scanf("%d", &c);
      --v, --c;
      tree_set(tin[v], tout[v], 1LL << c);
    } else {
      ans.push_back(get(v - 1));
    }
  }
  for (int i = 0; i < (int)(ans.size()); ++i) printf("%d\n", ans[i]);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  solve();
  return 0;
}
