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