dfs序+线段树+set存颜色T了。
我竟然没想到可以用long long来存颜色,这次吸取教训了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int maxn = 4e5 + 50; typedef long long st; st color[maxn << 2]; st lazy[maxn << 2]; int p[maxn], newq[maxn]; void merge1(st &last, st &l) { last |= l; } void push_up(int q) { color[q] = 0; merge1(color[q], color[q << 1]); merge1(color[q], color[q << 1 | 1]); } void test(st q) { while(q) { printf("%d", (int)q & 1); q >>= 1; } printf(" "); } void build(int q, int l, int r) { if(l == r) { color[q] |= (1LL << (newq[l] - 1)); //test(color[q]); return; } int mid = (l + r) >> 1; build(q << 1, l, mid); build(q << 1 | 1, mid + 1, r); push_up(q); } void push_down(int q) { if(lazy[q]) { // printf("dasd "); color[q << 1] = 0; lazy[q << 1] = 0; merge1(color[q << 1], lazy[q]); merge1(lazy[q << 1], lazy[q]); color[q << 1 | 1] = 0; lazy[q << 1 | 1] = 0; merge1(color[q << 1 | 1], lazy[q]); merge1(lazy[q << 1 | 1], lazy[q]); lazy[q] = 0; } } void upd(int q, int l, int r, int ql, int qr, int val) { if(l <= ql && qr <= r) { color[q] = 0; color[q] |= (1LL << val); lazy[q] = 0; if(l != r) lazy[q] |= (1LL << val); // test(color[q]); // printf("%d %d ", q, color[q].size()); return; } push_down(q); // test(color[q]); int mid = (ql + qr) >> 1; if(l <= mid) upd(q << 1, l, r, ql, mid, val); if(r > mid) upd(q << 1 | 1, l, r, mid + 1, qr, val); push_up(q); //test(color[q]); // printf("%d %d ", q, color[q].size()); } st query(int q, int l, int r, int ql, int qr) { if(l <= ql && qr <= r) { return color[q]; } push_down(q); int mid = (ql + qr) >> 1; st tmp = 0, tmp1 = 0, tmp2 = 0; if(l <= mid) tmp1 = query(q << 1, l, r, ql ,mid); if(r > mid) tmp2 = query(q << 1 | 1, l, r, mid + 1, qr); merge1(tmp, tmp1); merge1(tmp, tmp2); // test(tmp); // test(tmp1); // test(tmp2); return tmp; } vector<int> g[maxn]; int ind = 0; int L[maxn], R[maxn]; void dfs(int u, int fa) { L[u] = ++ind; newq[ind] = p[u]; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == fa) continue; dfs(v, u); } R[u] = ind; } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &p[i]); for(int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); g[u].push_back(v), g[v].push_back(u); } dfs(1, -1); build(1, 1, n); for(int i = 1; i <= m; i++) { int t, v, c; scanf("%d", &t); if(t == 1) { scanf("%d %d", &v, &c); // printf("L R %d %d ", L[v], R[v]); upd(1, L[v], R[v], 1, n, c - 1); } else { scanf("%d", &v); st tmp = query(1, L[v], R[v], 1, n); int cnt = 0; while(tmp) { if(tmp & 1) cnt++; tmp >>= 1; } // int cnt = __builtin_popcount(tmp); printf("%d ", cnt); } } return 0; } /* 7 11 1 1 1 1 1 1 1 1 2 1 3 1 4 3 5 3 6 3 7 1 3 2 2 1 2 2 1 4 3 2 1 1 2 5 2 1 1 6 4 2 1 2 2 2 3 */