1. 程式人生 > 其它 >New Year Tree(dfs序+線段樹+二進位制)

New Year Tree(dfs序+線段樹+二進位制)

技術標籤:codeforcesdfs序

題意: 給出一棵 n個節點的樹,根節點為 1。每個節點上有一種顏色 ci。m次操作。操作有兩種:
1 u c:將以 u為根的子樹上的所有節點的顏色改為c。
2 u:詢問以 u為根的子樹上的所有節點的顏色數量。

題解:
一看題目好像是個dfs序+線段樹的板子題,但是需要思考的是,怎麼查詢一段區間的顏色數目呢?
如果把這個問題解決了的話,這個題目也就相應的解決了。
看到顏色數目好像並不多,嗷,極好,60(2^60)正好在ll的範圍內。
我們可以考慮每一位儲存一種顏色,返回值為這段區間的**(或)|**。
這樣子dfs序建線段樹跑一邊即可。

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline") #include<bits/stdc++.h> #define endl '\n' #define int long long using namespace std; const int maxn=3e6+10; vector<int> edge[maxn]; int tree[maxn],add[maxn]; int a[maxn],in[maxn],out[maxn],id[maxn]; int cnt; void dfs(int u,int
fa){ in[u]=++cnt; id[cnt]=u; for(auto i:edge[u]){ if(i==fa) continue; dfs(i,u); } out[u]=cnt; } void build(int node,int start,int ends){ if(start==ends){ tree[node]=1ll<<(a[id[start]]); //cout<<"tree: "<<a[id[start]]<<" "<<tree[node]<<endl;
return ; } int mid=(start+ends)/2; build(node*2,start,mid); build(node*2+1,mid+1,ends); tree[node]=tree[node*2]|tree[node*2+1]; } void Add(int node,int val){ //cout<<"val"<<val<<endl; add[node]=val; tree[node]=1ll<<val; //cout<<"addnode "<<tree[node]<<endl; return ; } void push_down(int node){ if(add[node]==0) return ; Add(node*2,add[node]); Add(node*2+1,add[node]); add[node]=0; } void update(int node,int start,int ends,int l,int r,int val){ if(start>=l&&ends<=r) return Add(node,val); int mid=(start+ends)/2; push_down(node); if(l<=mid) update(node*2,start,mid,l,r,val); if(mid<r) update(node*2+1,mid+1,ends,l,r,val); tree[node]=tree[node*2]|tree[node*2+1]; } int query(int node,int start,int ends,int l,int r){ if(start>=l&&ends<=r){ //cout<<"tree[node]"<<l<<tree[node]<<endl; return tree[node]; } int mid=(start+ends)/2; push_down(node); int ans=0; if(l<=mid) ans|=query(node*2,start,mid,l,r); if(mid<r) ans|=query(node*2+1,mid+1,ends,l,r); return ans; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=0;i<n-1;i++){ int x,y; cin>>x>>y; edge[x].push_back(y); edge[y].push_back(x); } dfs(1,-1); //cout<<"okok"<<endl; build(1,1,n); //cout<<"okok"<<endl; for(int i=0;i<m;i++){ int opt; cin>>opt; if(opt==1){ int x,y; cin>>x>>y; //cout<<in[x]<<" "<<out[x]<<endl; update(1,1,n,in[x],out[x],y); } else{ int x; cin>>x; //cout<<"in:"<<in[x]<<" out:"<<out[x]<<endl; int xxx=query(1,1,n,in[x],out[x]); int ans=0; //cout<<"xxx="<<xxx<<endl; for(int i=0;i<=60;i++){ if(1&(xxx>>i)){ ans++; //cout<<i<<" "; } } //cout<<endl; cout<<ans<<endl; } } return 0; }