传送门
//题意: 对于一棵树以1为根的树, 每个结点有一种颜色. 现在有两种操作.
1 x y 把以x为根节点的子树中的所有节点染成颜色y
2 x 询问以x为根节点的子树中有多少种颜色的节点
//思路: 很明显的DFS序, 需要考虑几点, 涉及到线段树的区间修改. 然后就是颜色的计数, 由于颜色最多60种, 那么用long long 的二进制来表示它的颜色. 这样再pushup时直接左右子树或起来就行. 注意一个坑点就是在DFS序中的线段树描述的是各个节点的序了!!! 不再是每一个节点本身. 所以在build中, tree[id].val = a[dfsxu[l]] (dfsxu表示的是当前节点在dfs序中代表的节点!!!), 而不是a[l] !!! 这个BUG调了我好久. 要多做做这方面的题啊.
AC Code
/** @Cain*/
const int maxn = 4e5+5;
int cas=1;
ll a[maxn];
int dfs_xx[maxn];
struct node{
int tl, tr; ll val, maxx, lazy;
void fun(ll tmp) { //如果是直接加值就用 +=
lazy = tmp;
val = 1ll<<(tmp-1);
//maxx = tmp;
}
} tree[maxn*4];
void pushup(int id)
{
tree[id].val = tree[id<<1].val|tree[id<<1|1].val;
//tree[id].maxx = max(tree[id<<1].maxx,tree[id<<1|1].maxx);
}
void pushdown(int id)
{
if(tree[id].lazy){
tree[id<<1].fun(tree[id].lazy);
tree[id<<1|1].fun(tree[id].lazy);
tree[id].lazy = 0;
}
}
void build(int id,int l,int r)
{
tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0;
if(l == r){
tree[id].val = a[dfs_xx[l]]; //这是一个坑点啊.就如上面我所说.
return ;
}
int mid = (l+r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
void update(int id,int st,int ed,int val)
{
int l=tree[id].tl, r=tree[id].tr;
if(st <= l && r <= ed){
tree[id].fun(val);
return ;
}
pushdown(id);
int mid = (l+r) >> 1;
if(st <= mid) update(id<<1,st,ed,val);
if(ed > mid) update(id<<1|1,st,ed,val);
pushup(id);
}
ll query(int id,int ql,int qr)
{
int l = tree[id].tl , r = tree[id].tr;
if(ql <= l && r <= qr) return tree[id].val;
pushdown(id);
int mid = (l+r) >> 1 ;
ll res = 0;
if(ql <= mid) res |= query(id<<1,ql,qr);
if(qr > mid) res |= query(id<<1|1,ql,qr);
return res;
}
struct edge
{
int to,next;
ll w;
}s[maxn];
int cnt,ti,head[maxn];
int p1[maxn],p2[maxn];
void add(int u,int v,ll w)
{
s[cnt] = (edge){v,head[u],w};
head[u] = cnt++;
}
void dfs_id(int u,int fa)
{
p1[u] = ++ti;
dfs_xx[ti] = u;
for(int i=head[u]; ~i ; i = s[i].next){
int to = s[i].to;
if(fa == to) continue;
dfs_id(to,u);
}
p2[u] = ti;
}
void solve()
{
int n,q;
ll b[50];
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
ll u; scanf("%lld",&u);
b[i] = u;
a[i] = 1ll<<(u-1);
}
ti = cnt = 0; Fill(head,-1);
for(int i=1;i<=n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v,1);
add(v,u,1);
}
dfs_id(1,-1);
build(1,1,n);
while(q--){
int op; scanf("%d",&op);
if(op == 1) {
int u,v;
scanf("%d%d",&u,&v);
update(1,p1[u],p2[u],v);
}
else {
int u; scanf("%d",&u);
ll x = query(1,p1[u],p2[u]);
int cnt = 0;
while(x){
if(x&1) cnt++;
x >>= 1;
}
printf("%d\n",cnt);
}
}
}