cf-edu#6- E - New Year Tree -dfs序+线段树维护

http://codeforces.com/contest/620/problem/E


C《60,n<=1e5

题意:给你n个节点的 无向有根树 

给你每个节点的初始颜色ci

q次操作

操作1:1 v k 把v节点的所有子节点颜色都换成k

操作2:2 v 查询v节点的所有子节点颜色种类


先dfs跑一遍得到 一个dfs序

把每个节点涂上初始颜色, 每个节点在dfs序中的位置是in[i], 也就是update(in[i],val);


这个颜色只有60种,我们用一个int64变量来表示即可


那么每次操作1 ,我们就update线段树的【 in[i],out[i]】区间为 值 1<<(kind-1);

每次操作2 ,就查询【 in[i],out[i]】的和


维护颜色种类的时候直接用|操作非常方便, 维护的一个值x,其二进制下1的个数代表其管辖区间的颜色种类


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iostream>
using namespace std;  
__int64 inf=15;
double eps=0.000001;    

const __int64 N=4*100000+5;
vector < vector<__int64> >  mp(N);
__int64 id;
__int64 in[N],out[N];   
__int64 vis[N];
void dfs1(__int64 x)
{
	in[x]=++id;
	vis[x]=1;  
	__int64 i;
	for (i=0;i<mp[x].size();i++)
	{
		__int64 v=mp[x][i];
		if (vis[v]) continue;
		dfs1(v);
	}
	out[x]=id;
}  
__int64 add[N*4];
__int64 sum[N*4];
void pushDown(__int64 i,__int64 l,__int64 r)
{
	if (add[i])
	{
		__int64 mid=(l+r)>>1;
		add[i<<1]=add[i];
		sum[i<<1]=add[i];
		add[i<<1|1]=add[i];
		sum[i<<1|1]=add[i];
		add[i]=0;
	}
}
void update(__int64 i,__int64 l ,__int64 r,__int64 ql,__int64 qr,__int64 val)
{
	if (l>qr||r<ql)
		return ;
	if (l>=ql&&r<=qr)
	{
		sum[i]=val;
		add[i]=val;
		return ;
	}
	pushDown(i,l,r);
	__int64 mid=(l+r)>>1;
	update(i<<1,l,mid,ql,qr,val);
	update(i<<1|1,mid+1,r,ql,qr,val);
	sum[i]=sum[i<<1]|sum[i<<1|1];
}
__int64 query(__int64 i,__int64 l,__int64 r,__int64 ql,__int64 qr )
{
	if (l>qr||r<ql)
		return 0;
	if (l>=ql&&r<=qr) 
		return sum[i]; 
	pushDown(i,l,r);
	__int64 mid=(l+r)>>1;
	__int64 ret1=query(i<<1,l,mid,ql,qr);
	__int64 ret2=query(i<<1|1,mid+1,r,ql,qr); 
	return ret1|ret2;

}
__int64 cc[N];
int main() 
{ 
	__int64 one=1;
	__int64 x,y,i;
	int n,q;
	cin>>n>>q;
	id=0;  
	for (i=1;i<=n;i++) 
		scanf("%I64d",&cc[i]);   
	for (i=1;i<=n-1;i++)
	{
		scanf("%I64d%I64d",&x,&y);
		mp[x].push_back(y);
		mp[y].push_back(x);
	}
	dfs1(1);  
	for (i=1;i<=n;i++)
	{ 
	 	__int64 xx=one<<(cc[i]-1);
		update(1,1,n,in[i],in[i],xx);
	}
	__int64 op,vv,kk;
	for (i=1;i<=q;i++)
	{
		scanf("%I64d",&op);
		if (op==1)
		{
			scanf("%I64d%I64d",&vv,&kk); 
			__int64 xx=one<<(kk-1);
			update(1,1,n,in[vv],out[vv],xx);
		}
		else
		{
			scanf("%I64d",&vv);
			__int64 ans=query(1,1,n,in[vv],out[vv]);
			__int64 cun=0;
			while(ans)
			{
			cun+=ans%2; ans>>=1;
			}
			printf("%I64d\n",cun);
		}
	} 
	return 0;
}


你可能感兴趣的:(cf-edu#6- E - New Year Tree -dfs序+线段树维护)