#include <bits/stdc++.h>
using namespace std;
const int maxn = 500005;
vector<int> vec[maxn];
int vis[maxn];
int id[maxn];
int post[maxn];
int a[maxn];
int topw = 0;
long long ans;
struct node {
  int left, right;
  long long num, lazy;
} tree[maxn * 4];
void dfs(int u) {
  vis[u] = 1;
  id[u] = ++topw;
  for (int i = 0; i < vec[u].size(); i++) {
    int v = vec[u][i];
    if (vis[v]) continue;
    dfs(v);
  }
  post[u] = topw;
}
void push_down(int i) {
  if (!tree[i].lazy) return;
  tree[i << 1].num = tree[i << 1 | 1].num = (1LL << tree[i].lazy);
  tree[i << 1].lazy = tree[i << 1 | 1].lazy = tree[i].lazy;
  tree[i].lazy = 0;
}
void push_up(int i) { tree[i].num = tree[i << 1].num | tree[i << 1 | 1].num; }
void build(int i, int left, int right) {
  tree[i].lazy = 0;
  tree[i].left = left;
  tree[i].right = right;
  if (left == right) {
    return;
  }
  int mid = (tree[i].left + tree[i].right) >> 1;
  build(i << 1, left, mid);
  build(i << 1 | 1, mid + 1, right);
}
void get_pos(int i, int aim, int w) {
  if (tree[i].left == aim && tree[i].right == aim) {
    tree[i].num = (1LL << w);
    return;
  }
  push_down(i);
  int mid = (tree[i].left + tree[i].right) >> 1;
  if (aim <= mid) get_pos(i << 1, aim, w);
  if (aim > mid) get_pos(i << 1 | 1, aim, w);
  push_up(i);
}
void update(int i, int left, int right, long long w) {
  if (tree[i].left == left && tree[i].right == right) {
    tree[i].lazy = w;
    tree[i].num = (1LL << w);
    return;
  }
  push_down(i);
  int mid = (tree[i].left + tree[i].right) >> 1;
  if (right <= mid)
    update(i << 1, left, right, w);
  else if (left > mid)
    update(i << 1 | 1, left, right, w);
  else {
    update(i << 1, left, mid, w);
    update(i << 1 | 1, mid + 1, right, w);
  }
  push_up(i);
  return;
}
void query(int i, int left, int right) {
  if (tree[i].left == left && tree[i].right == right) {
    ans |= tree[i].num;
    return;
  }
  push_down(i);
  int mid = (tree[i].left + tree[i].right) >> 1;
  if (right <= mid) {
    query(i << 1, left, right);
  } else if (left > mid) {
    query(i << 1 | 1, left, right);
  } else {
    query(i << 1, left, mid);
    query(i << 1 | 1, mid + 1, right);
  }
  push_up(i);
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    vec[u].push_back(v);
    vec[v].push_back(u);
  }
  topw = 0;
  dfs(1);
  build(1, 1, topw);
  for (int i = 1; i <= n; i++) {
    get_pos(1, id[i], a[i]);
  }
  while (m--) {
    int op;
    int x, y;
    scanf("%d", &op);
    if (op == 1) {
      scanf("%d%d", &x, &y);
      update(1, id[x], post[x], y);
    } else {
      ans = 0;
      scanf("%d", &x);
      query(1, id[x], post[x]);
      int cnt = 0;
      for (int i = 1; i <= 61; i++) {
        if (ans & (1LL << i)) cnt++;
      }
      printf("%d\n", cnt);
    }
  }
}
