Educational Codeforces Round 6 E. New Year Tree(dfs序+线段树+状态压缩)(妙题)

题目链接
在这里插入图片描述
在这里插入图片描述
题意:给定一棵树,给你两个操作,一是把v和它的子树的所有数变成x,二是查询v和它的子树中不同的数有几个。
思路:很妙的解法,由于值不超过60,所有之间可以用二进制或操作来判断不同的数的个数,比如2和3,我就变成100和1000,相或后就变成1100,只要查看最后的结果有几个1就是不同的数的个数,至于子树的话用线段树+dfs序就可以,线段树pushup的时候相或就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=4e5+1; 
vector<int>g[maxn];
int tot=0,num[maxn],b[maxn],in[maxn],out[maxn];
struct cxk{
	int l,r;
	ll lazy,sum;
}tree[maxn<<2];
void dfs(int u,int fa)
{
	in[u]=++tot;
	b[tot]=u;
	for(int to:g[u])
	{
		if(to==fa) continue;
		dfs(to,u);
	}
	out[u]=tot;
}
void pushup(int x)
{
	tree[x].sum=tree[x<<1].sum|tree[x<<1|1].sum;
}
void pushdown(int x)
{
	if(tree[x].lazy)
	{
		tree[x<<1].lazy=tree[x<<1|1].lazy=tree[x].lazy;
		tree[x<<1].sum=(1LL<<tree[x].lazy);
		tree[x<<1|1].sum=(1LL<<tree[x].lazy);
		tree[x].lazy=0;
	}
}
void build(int x,int l,int r)
{
	tree[x].l=l;tree[x].r=r;
	if(l==r){
		tree[x].sum=(1LL<<num[b[l]]);
		return ;
	} 
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	pushup(x); 
}
void update(int x,int l,int r,int v)
{
	if(l<=tree[x].l&&tree[x].r<=r) {
		tree[x].sum=(1LL<<v);
		tree[x].lazy=v;
		return ;
	}
	pushdown(x);
	int mid=(tree[x].l+tree[x].r)>>1;
	if(l<=mid) update(x<<1,l,r,v);
	if(mid<r) update(x<<1|1,l,r,v);
	pushup(x);
}
ll query(int x,int l,int r)
{
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].sum;
	pushdown(x);
	int mid=(tree[x].l+tree[x].r)>>1;
	ll ans=0;
	if(l<=mid) ans|=query(x<<1,l,r);
	if(mid<r) ans|=query(x<<1|1,l,r);
	pushup(x);
	return ans; 
}
int main()
{
	int n,m,u,v,op,x,y;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%d",&num[i]);
	for(int i=1;i<n;++i)
	{
		scanf("%d %d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u); 
	}
	dfs(1,0);
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%d",&op);
		if(op==1) scanf("%d %d",&x,&y),update(1,in[x],out[x],y);
		else{
			scanf("%d",&x);
			ll ans=query(1,in[x],out[x]),cnt=0;
			for(ll j=1;j<=61;++j)
			if((ans&(1LL<<j))) cnt++;
			printf("%lld\n",cnt);
		}
	}
	
}
发布了283 篇原创文章 · 获赞 0 · 访问量 7295

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105126816