620E New Year Tree(线段树维护状压)

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*f;
}

const int maxn=4e5+100;

//线段树+状压
//线段树的权值表示区间颜色的出现次数
typedef long long ll;
vector<int> g[maxn]; 
ll c[maxn<<2],lz[maxn<<2];
int a[maxn];
int w[maxn];
int n,q;
int dfn[maxn],tot,sz[maxn];
void dfs (int x,int pre) {
	dfn[x]=++tot;
	w[tot]=a[x];
	sz[x]=1;
	for (int y:g[x]) if (y!=pre) dfs(y,x),sz[x]+=sz[y];
}
void pushup (int i) {
	c[i]=(c[i<<1]|c[i<<1|1]);
}
void pushdown (int i) {
	if (lz[i]) {
		c[i<<1]=lz[i];
		lz[i<<1]=lz[i];
		c[i<<1|1]=lz[i];
		lz[i<<1|1]=lz[i];
		lz[i]=0;
	}
}
void build (int i,int l,int r)  {
	if (l==r) {
		c[i]=(1ll<<(w[l]-1));
		return;
	}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
	pushup(i);
}
void up (int i,int l,int r,int L,int R,int x) {
	if (l>=L&&r<=R) {
		c[i]=(1ll<<(x-1));
		lz[i]=(1ll<<(x-1));
		return;
	}
	pushdown(i);
	int mid=(l+r)>>1;
	if (L<=mid) up(i<<1,l,mid,L,R,x);
	if (R>mid) up(i<<1|1,mid+1,r,L,R,x);
	pushup(i);
}
long long query (int i,int l,int r,int L,int R) {
	if (l>=L&&r<=R) return c[i];
	pushdown(i);
	int mid=(l+r)>>1;
	long long ans=0;
	if (L<=mid) ans|=(query(i<<1,l,mid,L,R));
	if (R>mid) ans|=(query(i<<1|1,mid+1,r,L,R));
	return ans;
}
int main () {
	n=read();q=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1;i<n;i++) {
		int x=read();
		int y=read();
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0);
	build(1,1,n);
	while (q--) {
		int op=read();
		if (op==1) {
			int x=read();
			int y=read();
			up(1,1,n,dfn[x],dfn[x]+sz[x]-1,y);
		}
		else {
			int x=read();
			long long ans=query(1,1,n,dfn[x],dfn[x]+sz[x]-1);
			int cnt=0;
			for (int i=1;i<=60;i++) if (ans&(1ll<<(i-1))) cnt++;
			printf("%d\n",cnt);
		}
	}
}
posted @ 2021-05-23 13:59  zlc0405  阅读(34)  评论(0编辑  收藏  举报