Description
In this paper, an undirected tree with n points rooted in 1 is given. Two operations are performed:
1 v c: dye all the subtrees rooted in v into C color
2v: Query the number of different colors in a subtree rooted with V
Input
Two integers n and m i n the first row represent points and operands respectively, and then n integers C [i] represent the color of each point i n the initial state, then two integers u and v i n the n-1 row represent a tree edge, and finally one operation per line i n the m row (1<=n, m<=4e5, 1<=c[i]<=60).
Output
For each query operation, output the query results
Sample Input
7 10
1 1 1 1 1 1 1
1 2
1 3
1 4
3 5
3 6
3 7
1 3 2
2 1
1 4 3
2 1
1 2 5
2 1
1 6 4
2 1
2 2
2 3
Sample Output
2
3
4
5
1
2
Solution
After finding the dfs order of each point, each sub-tree is a continuous interval, and then the operation is changed into interval updating and interval query. The line segment tree can maintain the interval color. Since there are only 60 kinds of colors, it is enough to save a long long one.
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 400004
#define ls (t<<1)
#define rs ((t<<1)|1)
int n,m,c[maxn];
vector<int>g[maxn];
int index,L[maxn],R[maxn];
int Cover[maxn<<2];
ll C[maxn<<2];
void dfs(int u,int fa)
{
L[u]=++index;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v==fa)continue;
dfs(v,u);
}
R[u]=index;
}
void push_up(int t)
{
C[t]=C[ls]|C[rs];
}
void push_down(int t)
{
if(Cover[t])
{
C[ls]=C[rs]=C[t];
Cover[ls]=Cover[rs]=1;
Cover[t]=0;
}
}
void build(int l,int r,int t)
{
C[t]=Cover[t]=0;
if(l==r)return ;
int mid=(l+r)/2;
build(l,mid,ls),build(mid+1,r,rs);
}
void update(int L,int R,int l,int r,int t,ll v)
{
if(L<=l&&r<=R)
{
C[t]=v,Cover[t]=1;
return ;
}
push_down(t);
int mid=(l+r)/2;
if(L<=mid)update(L,R,l,mid,ls,v);
if(R>mid)update(L,R,mid+1,r,rs,v);
push_up(t);
}
ll query(int L,int R,int l,int r,int t)
{
if(L<=l&&r<=R||Cover[t])return C[t];
int mid=(l+r)/2;
ll ans=0;
if(L<=mid)ans|=query(L,R,l,mid,ls);
if(R>mid)ans|=query(L,R,mid+1,r,rs);
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
g[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);
}
index=0;
dfs(1,1);
build(1,n,1);
for(int i=1;i<=n;i++)
update(L[i],L[i],1,n,1,1ll<<c[i]);
while(m--)
{
int op,x,v;
scanf("%d%d",&op,&x);
if(op==1)
{
scanf("%d",&v);
update(L[x],R[x],1,n,1,1ll<<v);
}
else
{
ll temp=query(L[x],R[x],1,n,1);
int num=0;
for(int i=1;i<=60;i++)
if((1ll<<i)&temp)num++;
printf("%d\n",num);
}
}
}
return 0;
}