【题意】给定N=4*1e5个节点的树,有Q=4*1e5个操作,每次可以选择一个节点,把他的儿子结点全部染成一种颜色,还有就是查询某个节点最后有多少个颜色。
【解题方法】其实这题应该算是区间染色加DFS的板子题了。我用的是bitset压位来解决了区间染色问题。具体看代码吧。
【AC代码】
#include <cstdio>
#include <cstring>
#include <bitset>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=4e5+10;
int n,q,col[maxn];
/********************************DFS序部分*********************************/
vector<int>G[maxn];
int st[maxn],en[maxn],dfn;
void init(){
for(int i=1; i<=n; i++) G[i].clear();
}
void dfs(int u,int fa){
st[u]=++dfn;
for(int i=0; i<(int)G[u].size(); i++){
int v=G[u][i];
if(v!=fa) dfs(v,u);
}
en[u]=dfn;
}
/********************************线段树部分***********************************/
struct node{
int l,r,lazy;
bitset<61>c;
node(){}
void setColor(int col){
c.reset();
c[col]=1;
}
node(int l,int r):l(l),r(r){c.reset();}
}Tree[maxn*4];
node operator+(node a,node b){
node ret(a.l,b.r);
ret.c=a.c|b.c;
return ret;
}
void pushup(int rt){
Tree[rt].c=Tree[rt*2].c|Tree[rt*2+1].c;
}
void pushdwon(int rt){
if(Tree[rt].lazy){
Tree[rt*2].setColor(Tree[rt].lazy);
Tree[rt*2+1].setColor(Tree[rt].lazy);
Tree[rt*2].lazy=Tree[rt*2+1].lazy=Tree[rt].lazy;
Tree[rt].lazy=0;
}
}
void Build(int l,int r,int rt){
Tree[rt].l=l,Tree[rt].r=r;
Tree[rt].lazy=0;
if(l==r) return ;
int mid=(l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
}
void update(int L,int R,int c,int rt){
if(L==Tree[rt].l&&Tree[rt].r==R){
Tree[rt].lazy=c;
Tree[rt].setColor(c);
return ;
}
pushdwon(rt);
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) update(L,R,c,rt*2);
else if(L>mid) update(L,R,c,rt*2+1);
else{
update(L,mid,c,rt*2);
update(mid+1,R,c,rt*2+1);
}
pushup(rt);
}
node queryans(int L,int R,int rt){
if(L==Tree[rt].l&&Tree[rt].r==R){
return Tree[rt];
}
pushdwon(rt);
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) return queryans(L,R,rt*2);
else if(L>mid) return queryans(L,R,rt*2+1);
else{
return queryans(L,mid,rt*2)+queryans(mid+1,R,rt*2+1);
}
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1; i<=n; i++) G[i].clear();
for(int i=1; i<=n; i++) scanf("%d",&col[i]);
Build(1,n,1);
//puts("success");
for(int i=1; i<n; i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
//dfs序
dfn=0;
dfs(1,-1);
int x,y;
for(int i=1; i<=n; i++) update(st[i],st[i],col[i],1);
while(q--){
int op;
scanf("%d",&op);
if(op==1){
scanf("%d%d",&x,&y);
update(st[x],en[x],y,1);
}else{
scanf("%d",&x);
node ans=queryans(st[x],en[x],1);
int sum=ans.c.count();
printf("%d\n",sum);
}
}
}