关于子树的修改和查询

很容易想到树链剖分

序建立线段树

线段树中保存每个节点的颜色信息

由于颜色最多种所以可以压缩为二进制数

然后维护一个懒标记,就是裸题了

(另外,我是真不喜欢写树的题啊!!!!!)

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
typedef long long ll;
const int maxn = 8e5+10;
struct edge{
    int to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v){ d[++cnt] = (edge){v,head[u]},head[u]=cnt; }
int fa[maxn],deep[maxn],son[maxn],siz[maxn],w[maxn],n,m;
void dfs1(int u,int f,int depth)
{
    deep[u] = depth; siz[u] = 1; fa[u] = f;
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v==f )    continue;
        dfs1(v,u,depth+1);
        siz[u] += siz[v];
        if( siz[son[u]]<siz[v] )    son[u] = v;
    }
}
ll wn[maxn];
int id[maxn],kl,top[maxn];
void dfs2(int u,int ffa )
{
    id[u] = ++kl,wn[kl] = 1ll<<w[u],top[u] = ffa;
    if( son[u]==0 )    return;
    dfs2( son[u],ffa );
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v==fa[u]||v==son[u] )    continue;
        dfs2(v,v);
    }
}
ll laz[maxn<<1],a[maxn<<1];
void pushup(int rt,int l,int r)    { a[rt] = a[ls]|a[rs]; }
void pushdown(int rt,int l,int r)
{
    if( laz[rt]==0 )    return;
    a[ls]=a[rs]=laz[ls]=laz[rs]=laz[rt];
    laz[rt]=0;
}
void build(int rt,int l,int r)
{
    if( l==r ){ a[rt]=wn[l]; return; }
    build( lson ); build( rson );
    pushup(rt,l,r);
}
void update(int rt,int l,int r,int L,int R,ll val)
{
    if( l>R||r<L )    return;
    if( l>=L&&r<=R ) { a[rt]=laz[rt]=val; return; }
    pushdown(rt,l,r);
    update(lson,L,R,val); update(rson,L,R,val);
    pushup(rt,l,r);
}
ll ask(int rt,int l,int r,int L,int R)
{
    if( l>R||r<L )    return 0;
    if( l>=L&&r<=R )    return a[rt];
    pushdown(rt,l,r);
    return ask(lson,L,R)|ask(rson,L,R);
}
int zhuan(ll x){ int ans = 0; while( x ){ ans += (x&1); x>>=1; } return ans; }
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)    scanf("%d",&w[i] );
    for(int i=1;i<n;i++)
    {
        int l,r; scanf("%d%d",&l,&r);
        add(l,r); add(r,l);
    }
    dfs1(1,0,1); dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int type,v,c; scanf("%d",&type);
        if( type==1 )
        {
            scanf("%d%d",&v,&c);
            update(1,1,n,id[v],id[v]+siz[v]-1,1ll<<c);
        }
        else
        {
            scanf("%d",&v);
            printf("%d\n",zhuan(ask(1,1,n,id[v],id[v]+siz[v]-1) ) );
        }
    }
}