// 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; }