// Problem: CF620E New Year Tree
// Memory Limit: 250 MB
// Time Limit: 3000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e5 + 50;
bitset <61> Ans;//注意一定要定义与下面的相同的长度,不然很不方便
int n,Q,tot = 0,now = 0;
int start[MAXN];
int data[MAXN],siz[MAXN],son[MAXN],deep[MAXN],fa[MAXN];
int dfn[MAXN],dfn_id[MAXN];
struct SegmentTree {
int l,r;
bitset <61> B;
int F;
} T[MAXN * 4];
struct Edge {
int next,to;
void add(int from,int To) {next = start[from], to = To , start[from] = tot;}
} edge[MAXN * 2];
inline int read() {
int x = 0 , flag = 1;
char ch = getchar();
for( ; ch > '9' || ch < '0' ; ch = getchar());
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
int DFS1(int x,int from) {//求DFS序
siz[x] = 1, son[x] = 0;
deep[x] = deep[from] + 1 , fa[x] = from;
dfn[x] = ++now , dfn_id[now] = x;
for(int i = start[x] ; i ; i = edge[i].next) {
int to = edge[i].to;
if(to == from) continue;
int v = DFS1(to , x);
if(siz[v] > siz[son[x]]) son[x] = to;
siz[x] += v;
}
return siz[x];
}
void build(int x,int l,int r) {
T[x].l = l , T[x].r = r;
T[x].B = 0ll, T[x].F = 0ll;
if(l == r) {
T[x].B[data[dfn_id[l]]] = 1;//dfn_id表示的是Dfn序对应的原数组的下标
return ;
}
int mid = (l + r) >> 1;
build(x << 1 , l , mid);
build(x << 1 | 1 , mid + 1 , r);
T[x].B = T[x << 1].B | T[x << 1 | 1].B;//用或运算连接
return ;
}
void update(int x,int k) {
T[x].B.reset();//因为全部覆盖掉了,所以清空
T[x].B[k] = 1;
T[x].F = k;
return ;
}
void pushdown(int x) {//下传标记
if(T[x].F == 0ll) return ;
update(x << 1 | 1 , T[x].F);//这个F就是被覆盖的标记
update(x << 1 , T[x].F);
T[x].F = 0ll;
return ;
}
void change(int x,int l,int r,int k) {
if(T[x].l >= l && T[x].r <= r) {
update(x, k);
return ;
}
pushdown(x);
int mid = (T[x].l + T[x].r) >> 1;
if(l <= mid) change(x << 1 , l , r , k);
if(r > mid) change(x << 1 | 1 , l , r , k);
T[x].B = T[x << 1].B | T[x << 1 | 1].B;
return ;
}
void GetAns(int x,int l,int r) {// 统计答案,对于涉及到的区间用 "|" 运算来取得答案
if(T[x].l >= l && T[x].r <= r) {
Ans |= T[x].B;//前文提到了两个 bitset 类型的数组可以直接用位运算符号连接
return ;
}
pushdown(x);
int mid = (T[x].l + T[x].r) >> 1;
if(l <= mid) GetAns(x << 1 , l , r );
if(r > mid) GetAns(x << 1 | 1 , l , r);
return ;
}
int main() {
n = read() , Q = read();
for(int i = 1 ; i <= n ; i ++) data[i] = read();
for(int i = 1 ; i <= n - 1 ; i ++) {
int u = read() , v = read();
edge[++tot].add(u,v);
edge[++tot].add(v,u);
}
DFS1(1,0);//预处理
build(1 , 1 , n);
while(Q --) {
int op = read() , u = read() , c;
if(op == 1) c = read();
if(op == 1) change(1 , dfn[u] , dfn[u] + siz[u] - 1 , c);//子树修改
else {
Ans.reset();//这个是将 bitset 数组清空的函数
GetAns(1 , dfn[u] , dfn[u] + siz[u] - 1);
printf("%d\n",Ans.count());//bitset 的 count函数就是统计1的个数
}
}
return 0;
}