#include <bits/stdc++.h>
using namespace std;
int lg(long long n) {
  assert(n > 0);
  int ans = -1;
  while (n) {
    ans++;
    n >>= 1;
  }
  return ans;
}
struct SegmentTree {
  int n;
  vector<bitset<60>> sum;
  vector<int> mark;
  vector<bitset<60>> setval;
  SegmentTree(int n) : n(n), mark(4 * n), setval(4 * n) {}
  void Set(int id, int l, int r, bitset<60> val) {
    mark[id] = true;
    setval[id] = val;
    sum[id] = val;
  }
  void push(int id, int l, int r) {
    if (mark[id]) {
      int m = (l + r) >> 1;
      Set(id << 1, l, m, setval[id]);
      Set(id << 1 | 1, m + 1, r, setval[id]);
      mark[id] = false;
    }
  }
  void pull(int id) { sum[id] = sum[id << 1] | sum[id << 1 | 1]; }
  SegmentTree(const vector<int> &v) {
    n = (int)v.size();
    mark.assign(4 * n, 0);
    setval.resize(4 * n);
    sum.resize(4 * n);
    function<void(int, int, int)> build = [&](int id, int l, int r) {
      if (l == r) {
        sum[id] = bitset<60>(1LL << v[l]);
        return;
      }
      int m = (l + r) >> 1;
      build(id << 1, l, m);
      build(id << 1 | 1, m + 1, r);
      pull(id);
    };
    build(1, 0, n - 1);
  }
  void RangeSet(int id, int l, int r, int ql, int qr, int val) {
    if (l > qr || r < ql) return;
    if (ql <= l && r <= qr) {
      Set(id, l, r, bitset<60>(1LL << val));
      return;
    }
    push(id, l, r);
    int m = (l + r) >> 1;
    RangeSet(id << 1, l, m, ql, qr, val);
    RangeSet(id << 1 | 1, m + 1, r, ql, qr, val);
    pull(id);
  }
  void RangeSet(int ql, int qr, int val) { RangeSet(1, 0, n - 1, ql, qr, val); }
  bitset<60> GetSum(int id, int l, int r, int ql, int qr) {
    if (l > qr || r < ql) return 0;
    if (ql <= l && r <= qr) {
      return sum[id];
    }
    push(id, l, r);
    int m = (l + r) >> 1;
    return GetSum(id << 1, l, m, ql, qr) |
           GetSum(id << 1 | 1, m + 1, r, ql, qr);
  }
  bitset<60> GetSum(int ql, int qr) { return GetSum(1, 0, n - 1, ql, qr); }
  bitset<60> GetEle(int id, int l, int r, int pos) {
    if (l == r) {
      assert(l == pos);
      return sum[id];
    }
    push(id, l, r);
    int m = (l + r) >> 1;
    if (pos <= m) return GetEle(id << 1, l, m, pos);
    return GetEle(id << 1 | 1, m + 1, r, pos);
  }
  bitset<60> GetEle(int pos) { return GetEle(1, 0, n - 1, pos); }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> c(n);
  for (int i = 0; i < n; i++) {
    cin >> c[i];
    c[i]--;
  }
  vector<vector<int>> adj(n);
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  int T = 0;
  vector<int> tin(n), tout(n);
  function<void(int, int)> dfs = [&](int cur, int fa) {
    tin[cur] = T++;
    for (int nxt : adj[cur]) {
      if (nxt == fa) continue;
      dfs(nxt, cur);
    }
    tout[cur] = T - 1;
  };
  dfs(0, -1);
  vector<int> col_in_order(n);
  for (int i = 0; i < n; i++) {
    col_in_order[tin[i]] = c[i];
  }
  SegmentTree st(col_in_order);
  while (m--) {
    int op;
    cin >> op;
    if (op == 1) {
      int v, c;
      cin >> v >> c;
      v--, c--;
      st.RangeSet(tin[v], tout[v], c);
    } else if (op == 2) {
      int v;
      cin >> v;
      v--;
      cout << st.GetSum(tin[v], tout[v]).count() << '\n';
    } else
      assert(false);
  }
  return 0;
}
