[题目链接]
https://codeforces.com/contest/620/problem/E
[算法]
显然 , 一棵子树的DFS序必然为连续的一段
用线段树维护颜色数即可
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 4e5 + 10; struct edge { int to , nxt; } e[MAXN << 1]; int n , m , tot , timer; int a[MAXN],dfn[MAXN],pos[MAXN],size[MAXN],head[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } struct SegmentTree { struct Node { int l , r , tag; long long value; } Tree[MAXN << 2]; inline void update(int index) { Tree[index].value = Tree[index << 1].value | Tree[index << 1 | 1].value; } inline void build(int index,int l,int r) { Tree[index].l = l; Tree[index].r = r; Tree[index].tag = -1; Tree[index].value = 0; if (l == r) { Tree[index].value = 1ll * 1 << a[pos[l]]; return; } int mid = (l + r) >> 1; build(index << 1,l,mid); build(index << 1 | 1,mid + 1,r); update(index); } inline void pushdown(int index) { if (Tree[index].tag != -1) { Tree[index << 1].tag = Tree[index << 1 | 1].tag = Tree[index].tag; Tree[index << 1].value = Tree[index << 1 | 1].value = 1ll * 1 << Tree[index].tag; Tree[index].tag = -1; } } inline void modify(int index,int l,int r,int c) { if (Tree[index].l == l && Tree[index].r == r) { Tree[index].value = 1ll * 1 << c; Tree[index].tag = c; return; } pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) modify(index << 1,l,r,c); else if (mid + 1 <= l) modify(index << 1 | 1,l,r,c); else { modify(index << 1,l,mid,c); modify(index << 1 | 1,mid + 1,r,c); } update(index); } inline long long query(int index,int l,int r) { if (Tree[index].l == l && Tree[index].r == r) return Tree[index].value; pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) return query(index << 1,l,r); else if (mid + 1 <= l) return query(index << 1 | 1,l,r); else return query(index << 1,l,mid) | query(index << 1 | 1,mid + 1,r); } } T; inline void addedge(int u,int v) { tot++; e[tot] = (edge){v,head[u]}; head[u] = tot; } inline void dfs(int u,int fa) { dfn[u] = ++timer; pos[timer] = u; size[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == fa) continue; dfs(v,u); size[u] += size[v]; } } inline int calc(long long x) { int ret = 0; while (x > 0) { ret += x & 1; x >>= 1; } return ret; } int main() { read(n); read(m); for (int i = 1; i <= n; i++) { read(a[i]); a[i]--; } for (int i = 1; i < n; i++) { int x , y; read(x); read(y); addedge(x,y); addedge(y,x); } dfs(1,-1); T.build(1,1,n); while (m--) { int op; read(op); if (op == 1) { int v , col; read(v); read(col); T.modify(1,dfn[v],dfn[v] + size[v] - 1,--col); } else { int v; read(v); printf("%d ",calc(T.query(1,dfn[v],dfn[v] + size[v] - 1))); } } return 0; }