線段樹+Dfs序【CF620E】New Year Tree
阿新 • • 發佈:2018-11-03
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; } } }