#include <bits/stdc++.h>
using namespace std;
const int MAX = 4e5 + 9;
int n, q, sq, startRange[MAX], endRange[MAX];
long long lazy[700], c[MAX];
bool marked[700];
vector<int> adj[MAX], euler;
void dfs(int cur, int par = -1) {
  euler.push_back(cur);
  startRange[cur] = euler.size() - 1;
  for (int i = 0; i < adj[cur].size(); ++i) {
    int child = adj[cur][i];
    if (child == par) {
      continue;
    }
    dfs(child, cur);
  }
  endRange[cur] = euler.size() - 1;
}
void pushLazy(int block) {
  marked[block] = 0;
  for (int i = block * sq, en = min(n - 1, (block + 1) * sq - 1); i <= en;
       ++i) {
    c[euler[i]] = lazy[block];
  }
}
void updBlock(int block, int l, int r, int newColor) {
  if (marked[block]) {
    pushLazy(block);
  }
  for (int i = l; i <= r; ++i) {
    c[euler[i]] = (1LL << newColor);
  }
  lazy[block] = 0;
  for (int i = block * sq, en = min(n - 1, (block + 1) * sq - 1); i <= en;
       ++i) {
    lazy[block] |= c[euler[i]];
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> n >> q;
  for (int i = 1; i <= n; ++i) {
    cin >> c[i];
    c[i] = (1LL << c[i]);
  }
  for (int i = 0; i < n - 1; ++i) {
    int x, y;
    cin >> x >> y;
    adj[x].push_back(y);
    adj[y].push_back(x);
  }
  sq = (int)sqrt(n + .0) + 1;
  dfs(1);
  for (int i = 0; i < n; ++i) {
    lazy[i / sq] |= c[euler[i]];
  }
  while (q--) {
    int type;
    cin >> type;
    if (type == 1) {
      int node, newColor;
      cin >> node >> newColor;
      int l = startRange[node], r = endRange[node], leftBlock = l / sq,
          rightBlock = r / sq;
      if (leftBlock == rightBlock) {
        updBlock(leftBlock, l, r, newColor);
      } else {
        updBlock(leftBlock, l, (leftBlock + 1) * sq - 1, newColor);
        updBlock(rightBlock, rightBlock * sq, r, newColor);
        for (int i = leftBlock + 1; i <= rightBlock - 1; ++i) {
          lazy[i] = (1LL << newColor);
          marked[i] = 1;
        }
      }
    } else {
      int node;
      cin >> node;
      int l = startRange[node], r = endRange[node], leftBlock = l / sq,
          rightBlock = r / sq;
      if (leftBlock == rightBlock) {
        if (marked[leftBlock]) {
          cout << 1 << "\n";
        } else {
          long long ans = 0;
          for (int i = l; i <= r; ++i) {
            ans |= c[euler[i]];
          }
          cout << __builtin_popcountll(ans) << "\n";
        }
      } else {
        if (marked[leftBlock]) pushLazy(leftBlock);
        if (marked[rightBlock]) pushLazy(rightBlock);
        long long ans = 0;
        for (int i = l, en = (leftBlock + 1) * sq - 1; i <= en; ++i) {
          ans |= c[euler[i]];
        }
        for (int i = leftBlock + 1; i <= rightBlock - 1; ++i) {
          ans |= lazy[i];
        }
        for (int i = rightBlock * sq; i <= r; ++i) {
          ans |= c[euler[i]];
        }
        cout << __builtin_popcountll(ans) << "\n";
      }
    }
  }
  return 0;
}
