#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
const int K = (int)log2(N) + 2;
const int SQRTN = (int)sqrt(N) + 7;
const long long infi = 1ll << 60;
vector<int> ett, adj[N];
int n, q, a, b, t, col[N];
long long tree[16 * N], lazy[16 * N];
pair<long long, long long> occ[N];
bool vis[N];
void dfs(int node) {
  if (vis[node]) return;
  vis[node] = true;
  ett.push_back(node);
  occ[node].first = ett.size() - 1;
  for (int i = 0; i < adj[node].size(); ++i) {
    dfs(adj[node][i]);
  }
  ett.push_back(node);
  occ[node].second = ett.size() - 1;
}
inline int left(int node) { return node << 1; }
inline int right(int node) { return left(node) | 1; }
void build(int node, int x, int y) {
  if (x > y) return;
  if (x == y) {
    tree[node] = (1ll << col[ett[x]]);
    return;
  }
  int mid = x + ((y - x) >> 1);
  build(left(node), x, mid);
  build(right(node), mid + 1, y);
  tree[node] = tree[left(node)] | tree[right(node)];
}
void update(int node, int leftmost, int rightmost, int x, int y,
            long long msk) {
  if (lazy[node]) {
    tree[node] = lazy[node];
    if (x != y) {
      lazy[left(node)] = lazy[node];
      lazy[right(node)] = lazy[node];
    }
    lazy[node] = 0;
  }
  if (x > y || x > rightmost || y < leftmost) return;
  if (x >= leftmost && y <= rightmost) {
    tree[node] = msk;
    if (x != y) {
      lazy[left(node)] = msk;
      lazy[right(node)] = msk;
    }
    return;
  }
  int mid = x + ((y - x) >> 1);
  update(left(node), leftmost, rightmost, x, mid, msk);
  update(right(node), leftmost, rightmost, mid + 1, y, msk);
  tree[node] = tree[left(node)] | tree[right(node)];
}
long long query(int node, int leftmost, int rightmost, int x, int y) {
  if (lazy[node]) {
    tree[node] = lazy[node];
    if (x != y) {
      lazy[left(node)] = lazy[node];
      lazy[right(node)] = lazy[node];
    }
    lazy[node] = 0;
  }
  if (x > y || x > rightmost || y < leftmost) return 0ll;
  if (x >= leftmost && y <= rightmost) return tree[node];
  int mid = x + ((y - x) >> 1);
  long long q1 = query(left(node), leftmost, rightmost, x, mid);
  long long q2 = query(right(node), leftmost, rightmost, mid + 1, y);
  return q1 | q2;
}
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  ;
  scanf("%d %d", &n, &q);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &col[i]);
    --col[i];
  }
  for (int i = 0; i < n - 1; ++i) {
    scanf("%d %d", &a, &b);
    --a, --b;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  dfs(0);
  n *= 2;
  build(1, 0, n - 1);
  while (q--) {
    scanf("%d", &t);
    if (t == 1) {
      scanf("%d %d", &a, &b);
      --a, --b;
      update(1, occ[a].first, occ[a].second, 0, n - 1, (1ll << b));
    } else {
      scanf("%d", &a);
      --a;
      long long msk = query(1, occ[a].first, occ[a].second, 0, n - 1);
      int ans = 0;
      for (int i = 0; i <= 60; ++i) {
        if (msk & (1ll << i)) ++ans;
      }
      printf("%d\n", ans);
    }
  }
  return 0;
}
