New Year Tree
题目链接:http://codeforces.com/problemset/problem/620/E
数据范围:略。
题解:
转化成序列问题,发现颜色种数特别少,暴力用数组合并显然会$T$,我们用$bitset$优化合并过程即可。
代码:
#include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) #define N 800010 #define ls p << 1 #define rs p << 1 | 1 using namespace std; char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() { int x = 0, f = 1; char c = nc(); while (c < 48) { if (c == '-') f = -1; c = nc(); } while (c > 47) { x = (((x << 2) + x) << 1) + (c ^ 48), c = nc(); } return x * f; } int head[N], to[N << 1], nxt[N << 1], tot; inline void add(int x, int y) { to[ ++ tot] = y; nxt[tot] = head[x]; head[x] = tot; } bitset <60> a[N << 2], tag[N << 2], val, ans; inline void pushup(int p) { a[p] = a[ls] | a[rs]; } inline void pushdown(int p) { if (tag[p].count()) { a[ls] = tag[ls] = tag[p]; a[rs] = tag[rs] = tag[p]; tag[p].reset(); } } void update(int x, int y, int l, int r, int p) { if (x <= l && r <= y) { a[p] = tag[p] = val; return; } int mid = (l + r) >> 1; pushdown(p); if (x <= mid) { update(x, y, l, mid, ls); } if (mid < y) { update(x, y, mid + 1, r, rs); } pushup(p); } void query(int x, int y, int l, int r, int p) { if (x <= l && r <= y) { ans = ans | a[p]; return; } int mid = (l + r) >> 1; pushdown(p); if (x <= mid) { query(x, y, l, mid, ls); } if (mid < y) { query(x, y, mid + 1, r, rs); } } int sz[N], dic[N], cnt, re[N]; void dfs(int p, int fa) { dic[p] = ++cnt, re[cnt] = p; sz[p] = 1; for (int i = head[p]; i; i = nxt[i]) { if (to[i] != fa) { dfs(to[i], p); sz[p] += sz[to[i]]; } } } int v[N]; void build(int l, int r, int p) { if (l == r) { a[p].set(v[re[l]] - 1); return; } int mid = (l + r) >> 1; build(l, mid, ls); build(mid + 1, r, rs); pushup(p); } int main() { // setIO("data-structure"); int n = rd(), m = rd(); for (int i = 1; i <= n; i ++ ) { v[i] = rd(); } for (int i = 1; i < n; i ++ ) { int x = rd(), y = rd(); add(x, y), add(y, x); } dfs(1, 1); build(1, n, 1); for (int i = 1; i <= m; i ++ ) { int opt = rd(); if (opt == 1) { int x = rd(), y = rd(); val.reset(); val.set(y - 1); update(dic[x], dic[x] + sz[x] - 1, 1, n, 1); } else { int x = rd(); ans.reset(); query(dic[x], dic[x] + sz[x] - 1, 1, n, 1); printf("%d ", ans.count()); } } fclose(stdin), fclose(stdout); return 0; }