luogu链接
题目大意:
有一个节点有颜色的树
操作1.修改子树的颜色
操作2.查询子树颜色的种类
注意,颜色种类小于60种
只有子树的操作,dfs序当然是最好的选择
dfs序列是什么,懒得讲了,自己搜吧
然后开两个数组,begin_和end_记录节点子树在dfs序数组中的开头和结尾
begin,end居然在cf是关键字,还好不是ccf,要不就死了
区间修改一个数,区间查询,线段树的傻逼操作
OK
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define ls rt<<1 #define rs rt<<1|1 #define ll long long const int max4 = 2e6 + 7; const int inf = 0x3f3f3f3f; int n, m; int w[max4], a[max4], begin_[max4], end_[max4]; struct node { int l, r, size, lazy; ll z; void color(int i) { z = z | (1LL << (i - 1)); } void clear() { z = 0LL; } } e[max4]; struct edge_edge { int v, nxt; } edge[max4]; int head[max4], e_tot; void add_edge(int u, int v) { edge[++e_tot].v = v; edge[e_tot].nxt = head[u]; head[u] = e_tot; } int count(ll z) { int js = 0; for (; z;) { if (z & 1) js++; z >>= 1; } return js; } int read() { int x = 0, f = 1; char s = getchar(); for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1; for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0'; return x * f; } void pushup(int rt) { e[rt].z = e[ls].z | e[rs].z; } void pushdown(int rt) { if (e[rt].lazy) { e[ls].clear(); e[rs].clear(); e[ls].color(e[rt].lazy); e[rs].color(e[rt].lazy); e[ls].lazy = e[rt].lazy; e[rs].lazy = e[rt].lazy; e[rt].lazy = 0; } } void build(int l, int r, int rt) { e[rt].l = l, e[rt].r = r; if (l == r) { e[rt].color(w[a[l]]); return; } int mid = (l + r) >> 1; build(l, mid, ls); build(mid + 1, r, rs); pushup(rt); } void update(int L, int R, int k, int rt) { if (L <= e[rt].l && e[rt].r <= R) { e[rt].clear(); e[rt].color(k); e[rt].lazy = k; return; } pushdown(rt); int mid = (e[rt].l + e[rt].r) >> 1; if (L <= mid) update(L, R, k, ls); if (R > mid) update(L, R, k, rs); pushup(rt); } ll query(int L, int R, int rt) { if (L <= e[rt].l && e[rt].r <= R) { return e[rt].z; } pushdown(rt); int mid = (e[rt].l + e[rt].r) >> 1; ll ans = 0; if (L <= mid) ans = ans | query(L, R, ls); if (R > mid) ans = ans | query(L, R, rs); pushup(rt); return ans; } void debug() { printf("debug\n"); printf(" %d\n", count(e[1].z)); printf(" %d %d\n", count(e[2].z), count(e[3].z) ); printf(" %d %d %d %d\n", count(e[4].z), count(e[5].z), count(e[6].z), count(e[7].z) ); printf(" %d %d %d %d %d %d %d %d\n", count(e[8].z), count(e[9].z), count(e[10].z), count(e[11].z), count(e[12].z), count(e[13].z), count(e[14].z), count(e[15].z)); } int js; void dfs(int u, int f) { a[++js] = u; begin_[u] = js; for (int i = head[u]; i; i = edge[i].nxt) { int v = edge[i].v; if (v == f) continue; dfs(v, u); } end_[u] = js; } int main() { n = read(), m = read(); for (int i = 1; i <= n; ++i) { w[i] = read(); } for (int i = 1; i < n; ++i) { int x = read(), y = read(); add_edge(x, y); add_edge(y, x); } dfs(1, 0); // cout << js << "\n"; // for (int i = 1; i <= n; ++i) // { // printf("%d ", a[i]); // } puts(""); // for (int i = 1; i <= n; ++i) // { // printf("%d => %d~~%d\n", i, begin_[i], end_[i]); // } build(1, n, 1); for (int i = 1; i <= m; ++i) { int tmp = read(); if (tmp == 1) { int a = read(), b = read(); update(begin_[a], end_[a], b, 1); } else { int a = read(); ll ans = query(begin_[a], end_[a], 1); printf("%d\n", count(ans)); } //debug(); } return 0; }
来源:https://www.cnblogs.com/dsrdsr/p/9758243.html