Description
你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]。
有两种操作:
1 v c 将以v为根的子树中所有点颜色更改为c
2 v 查询以v为根的子树中的节点有多少种不同的颜色
Input
第一行,两个整数\(n,m\),分别代表有\(n\)个节点和\(m\)个操作。
第二行,共\(n\)个整数,代表每个节点的初始颜色\(c[i]\)
接下来\(n-1\)行,描述一条边。
接下来\(m\)行,代表每个操作。
Output
对于每个询问操作,输出一行。
刚开始以为是树剖?
结果发现只需要对每个子树操作。
线段树维护\(dfs\)序。
对于颜色呢?发现\(c[i] \leq 60\)
开$long long $可以压成一个数。
因此我们将颜色压缩即可。
记得开$long long $
虽然没出第二个样例,但我切了
代码
#include<cstdio> #include<iostream> #include<algorithm> #define int long long #define R register using namespace std; const int gz=4e5+8; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int head[gz],tot; struct cod{int u,v;}edge[gz<<1]; inline void add(R int x,R int y) { edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot; } int dfn[gz],fdfn[gz],idx,size[gz]; void dfs(R int u,R int fa) { dfn[u]=++idx;fdfn[idx]=u;size[u]=1; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs(edge[i].v,u); size[u]+=size[edge[i].v]; } } int tr[gz<<2],c[gz],n,m; bool tg[gz<<2]; #define ls o<<1 #define rs o<<1|1 inline void up(R int o) { tr[o]=(tr[ls] | tr[rs]); } void build(R int o,R int l,R int r) { if(l==r) { tr[o]=(1LL<<c[fdfn[l]]); return ; } R int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); up(o); } inline void down(R int o) { if(tg[o]) { tg[ls]=tg[rs]=tg[o]; tr[ls]=tr[rs]=tr[o]; tg[o]=false; } } void change(R int o,R int l,R int r,R int x,R int y,R int k) { if(x<=l and y>=r){tr[o]=(1LL<<k);tg[o]=true;return;} down(o); R int mid=(l+r)>>1; if(x<=mid)change(ls,l,mid,x,y,k); if(y>mid)change(rs,mid+1,r,x,y,k); up(o); } int query(R int o,R int l,R int r,R int x,R int y) { if(x<=l and y>=r)return tr[o]; down(o); R int mid=(l+r)>>1; if(y<=mid)return query(ls,l,mid,x,y); else if(x>mid)return query(rs,mid+1,r,x,y); return (query(ls,l,mid,x,mid) | query(rs,mid+1,r,mid+1,y)); } #define lowbit(o) o&-o inline int tquery(R int v) { R int k=query(1,1,n,dfn[v],dfn[v]+size[v]-1); R int cnt=0; while(k) k-=lowbit(k),cnt++; return cnt; } signed main() { in(n);in(m); for(R int i=1;i<=n;i++)in(c[i]); for(R int i=1,x,y;i<n;i++) { in(x),in(y); add(x,y); add(y,x); } dfs(1,0);build(1,1,n); for(R int i=1,opt,v,c;i<=m;i++) { in(opt); switch(opt) { case 1:in(v),in(c);change(1,1,n,dfn[v],dfn[v]+size[v]-1,c);break; case 2:in(v);printf("%lld\n",tquery(v));break; } } }
来源:https://www.cnblogs.com/-guz/p/9901528.html