题意
- 给你一棵树,支持两个操作,\(1\)把一个子树的颜色更改为\(c\),\(2\)是询问一个子树内的颜色数,颜色数\(<=60\)
观察到颜色数不超过\(long\ long\)
可以把颜色压成一个长整形数
利用\(dfs\)序把树上操作变成区间操作
用线段树维护即可
有一个要注意的地方
__builtin_popcount 默认为\(int\)
要调用__builtin_popcountll
Codes
#include <bits/stdc++.h>
using namespace std;
#define For(i, a, b) for (register int i = (a), i##_end = b; i <= i##_end; ++ i)
#define FOR(i, a, b) for (register int i = (a), i##_end = b; i >= i##_end; -- i)
#define go(x, i) for (register int i = head[x]; i; i = nxt[i])
#define getc getchar_unlocked
#define putc putchar_unlocked
#define inf (0x3f3f3f3f)
#define INF (2e18)
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define y1 igniubi
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef long double ldb;
typedef double db;
typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
inline void procStatus() {
ifstream t("/proc/self/status");
cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>());
}
const int N = 4e5 + 10;
int to[N << 1], nxt[N << 1], head[N], e;
int a[N], st[N], ed[N], rel[N], n, q, cnt;
void add(int x, int y) {
to[++ e] = y; nxt[e] = head[x]; head[x] = e;
}
void dfs(int x, int dad) {
rel[st[x] = ++ cnt] = x;
go(x, i) if(to[i] ^ dad)
dfs(to[i], x);
ed[x] = cnt;
}
struct Segment_Tree {
#define ls (bh << 1)
#define rs (ls | 1)
#define mid ((l + r) >> 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
ll S[N << 2], tag[N << 2];
void pushup(int bh) {
S[bh] = S[ls] | S[rs];
}
void pushdown(int bh) {
if (tag[bh]) S[ls] = S[rs] = tag[ls] = tag[rs] = tag[bh], tag[bh] = 0;
}
void build(int bh, int l, int r) {
if (l == r) S[bh] = 1ll << (a[rel[l]] - 1);
else build(lson), build(rson), pushup(bh);
}
void update(int bh, int l, int r, int x, int y, int z) {
if (x <= l && r <= y)
S[bh] = tag[bh] = 1ll << (z - 1);
else {
pushdown(bh);
if (x <= mid) update(lson, x, y, z);
if (y > mid) update(rson, x, y, z);
pushup(bh);
}
}
ll query(int bh, int l, int r, int x, int y) {
if (x <= l && r <= y) return S[bh];
pushdown(bh);
if (x > mid) return query(rson, x, y);
if (y <= mid) return query(lson, x, y);
return query(lson, x, y) | query(rson, x, y);
}
}T;
int main() {
//freopen("CF620E.in", "r", stdin);
//freopen("CF620E.out", "w", stdout);
int opt, x, y;
scanf("%d%d", &n, &q);
For(i, 1, n) scanf("%d", &a[i]);
For(i, 2, n) {
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
dfs(1, 0), T.build(1, 1, n);
while (q --) {
scanf("%d%d", &opt, &x);
if (opt == 1) scanf("%d", &y), T.update(1, 1, n, st[x], ed[x], y);
else printf("%d\n", __builtin_popcountll(T.query(1, 1, n, st[x], ed[x])));
}
return 0;
}