New Year Tree
给出一棵树,每个结点刚开始的时候都有一个颜色,现在有查询
1 u col:给这个结点及其子树染上col这种颜色
2 u:查询以u为根节点的子树的所有颜色种类
/* 维护子树信息,应该想到求出dfs序,在序列上维护,用线段树或者树状数组什么的搞一搞 对于这个题: 遍历树一边,得出dfs序 建一棵线段树,每个节点维护一个long long 的val值(val分为60位分别状压60种颜色)表示当前区间是否存在某种颜色 然后标记下传同理,然后就是线段树区间修改区间查询了 非常要注意的是1<<i会爆,一定要写1LL<<i */ #include<iostream> #include<cstdio> #define maxn 400010 using namespace std; int xu[maxn],num,head[maxn],n,p,sz[maxn],opl,opr,opv,mp[maxn],color[maxn]; struct node{int to,pre;}e[maxn*2]; struct Node{int l,r;long long col,lazy;}tr[maxn*16]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void build(int l,int r,int k){ tr[k].l=l;tr[k].r=r; if(l==r){ int x; tr[k].col=(1<<color[mp[l]]-1); return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); tr[k].col=tr[k<<1].col|tr[k<<1|1].col; } int id; void dfs(int now,int father){ xu[now]=++id;mp[id]=now; sz[now]=1; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==father)continue; dfs(to,now); sz[now]+=sz[to]; } } int count(long long x){ int res=0; while(x){ res++; x-=(x&-x); } return res; } void update(int k){ tr[k<<1].lazy=tr[k].lazy; tr[k<<1].col=tr[k].lazy; tr[k<<1|1].lazy=tr[k].lazy; tr[k<<1|1].col=tr[k].lazy; tr[k].lazy=0; } void change(int l,int r,int k){ if(l>=opl&&r<=opr){ tr[k].col=1<<opv-1; tr[k].lazy=1<<opv-1; return; } if(tr[k].lazy)update(k); int mid=(l+r)>>1; if(opl<=mid)change(l,mid,k<<1); if(opr>mid)change(mid+1,r,k<<1|1); tr[k].col=tr[k<<1].col|tr[k<<1|1].col; } long long query(int l,int r,int k){ if(l>=opl&&r<=opr)return tr[k].col; if(tr[k].lazy)update(k); int mid=(l+r)>>1; long long res=0; if(opl<=mid)res|=query(l,mid,k<<1); if(opr>mid)res|=query(mid+1,r,k<<1|1); tr[k].col=tr[k<<1].col|tr[k<<1|1].col; return res; } int co(long long x){ for(int i=1;i<=6;i++){ if(x&(1<<i))return i; } } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&p); for(int i=1;i<=n;i++)scanf("%d",&color[i]); int op,x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); Insert(x,y);Insert(y,x); } dfs(1,0);build(1,n,1); for(int i=1;i<=p;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d",&x,&opv); opl=xu[x],opr=xu[x]+sz[x]-1; change(1,n,1); } if(op==2){ scanf("%d",&x); opl=xu[x],opr=xu[x]+sz[x]-1; long long w=query(1,n,1); printf("%d ",count(w)); } } }