#include <bits/stdc++.h>
using namespace std;
int n, c, m, quest;
long long co;
long long ST[2200010], Lazy[2200010], Color[400005];
vector<int> Adj[400005];
pair<int, int> Pos[400005];
void TrueVal(int node, int l, int r) {
  if (Lazy[node]) {
    ST[node << 1] = ST[node << 1 | 1] = Lazy[node << 1] = Lazy[node << 1 | 1] =
        Lazy[node];
  }
  Lazy[node] = 0;
}
void Update(int node, int l, int r, int u, int v, long long c) {
  TrueVal(node, l, r);
  if (l > v or r < u or l > r) {
    return;
  }
  if (v >= r and u <= l) {
    ST[node] = Lazy[node] = c;
    TrueVal(node, l, r);
    return;
  }
  int mid = (l + r) / 2;
  Update(node << 1, l, mid, u, v, c);
  Update((node << 1) + 1, mid + 1, r, u, v, c);
  ST[node] = ST[(node << 1)] | ST[(node << 1) + 1];
}
long long Get(int node, int l, int r, int u, int v) {
  TrueVal(node, l, r);
  if (l > v or u > r or l > r) {
    return 0;
  }
  if (v >= r and u <= l) {
    return ST[node];
  }
  int mid = (l + r) / 2;
  return Get(node << 1, l, mid, u, v) | Get((node << 1) + 1, mid + 1, r, u, v);
}
void ConstructEulerTour(int node, int p = -1) {
  Pos[node].first = c++;
  for (auto &x : Adj[node]) {
    if (x != p) {
      ConstructEulerTour(x, node);
    }
  }
  Pos[node].second = c - 1;
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> Color[i];
  }
  for (int i = 2; i <= n; ++i) {
    cin >> c >> quest;
    Adj[c].emplace_back(quest);
    Adj[quest].emplace_back(c);
  }
  c = 1;
  ConstructEulerTour(1);
  for (int i = 1; i <= n; i++) {
    co = 1ll << Color[i];
    Update(1, 1, n, Pos[i].first, Pos[i].first, co);
  }
  for (int i = 1; i <= m; ++i) {
    cin >> quest;
    if (quest == 2) {
      cin >> c;
      cout << __builtin_popcountll(Get(1, 1, n, Pos[c].first, Pos[c].second))
           << "\n";
    }
    if (quest == 1) {
      cin >> quest >> co;
      Update(1, 1, n, Pos[quest].first, Pos[quest].second, 1ll << co);
    }
  }
}
