线段树+Dfs序【CF620E】New Year Tree

Description

你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]。

有两种操作:

1 v c 将以v为根的子树中所有点颜色更改为c

2 v 查询以v为根的子树中的节点有多少种不同的颜色

Input

第一行,两个整数\(n,m\),分别代表有\(n\)个节点和\(m\)个操作。

第二行,共\(n\)个整数,代表每个节点的初始颜色\(c[i]\)

接下来\(n-1\)行,描述一条边。

接下来\(m\)行,代表每个操作。

Output

对于每个询问操作,输出一行。

刚开始以为是树剖?

结果发现只需要对每个子树操作。

线段树维护\(dfs\)序。

对于颜色呢?发现\(c[i] \leq 60\)

开$long  long $可以压成一个数。

因此我们将颜色压缩即可。

记得开$long  long $

虽然没出第二个样例,但我切了

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long 
#define R register

using namespace std;

const int gz=4e5+8;

inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

int head[gz],tot;

struct cod{int u,v;}edge[gz<<1];

inline void add(R int x,R int y)
{
    edge[++tot].u=head[x];
    edge[tot].v=y;
    head[x]=tot;
}

int dfn[gz],fdfn[gz],idx,size[gz];

void dfs(R int u,R int fa)
{
    dfn[u]=++idx;fdfn[idx]=u;size[u]=1;
    for(R int i=head[u];i;i=edge[i].u)
    {
        if(edge[i].v==fa)continue;
        dfs(edge[i].v,u);
        size[u]+=size[edge[i].v];
    }
}

int tr[gz<<2],c[gz],n,m;

bool tg[gz<<2];

#define ls o<<1
#define rs o<<1|1

inline void up(R int o)
{
    tr[o]=(tr[ls] | tr[rs]);
}

void build(R int o,R int l,R int r)
{
    if(l==r)
    {
        tr[o]=(1LL<<c[fdfn[l]]);
        return ;
    }
    R int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(o);
}

inline void down(R int o)
{
    if(tg[o])
    {
        tg[ls]=tg[rs]=tg[o];
        tr[ls]=tr[rs]=tr[o];
        tg[o]=false;
    }
}

void change(R int o,R int l,R int r,R int x,R int y,R int k)
{
    if(x<=l and y>=r){tr[o]=(1LL<<k);tg[o]=true;return;}
    down(o);
    R int mid=(l+r)>>1;
    if(x<=mid)change(ls,l,mid,x,y,k);
    if(y>mid)change(rs,mid+1,r,x,y,k);
    up(o);
}

int query(R int o,R int l,R int r,R int x,R int y)
{
    if(x<=l and y>=r)return tr[o];
    down(o);
    R int mid=(l+r)>>1;
    if(y<=mid)return query(ls,l,mid,x,y);
    else if(x>mid)return query(rs,mid+1,r,x,y);
    return (query(ls,l,mid,x,mid) | query(rs,mid+1,r,mid+1,y));
}

#define lowbit(o) o&-o 

inline int tquery(R int v)
{
    R int k=query(1,1,n,dfn[v],dfn[v]+size[v]-1);
    R int cnt=0;
    while(k) k-=lowbit(k),cnt++;
    return cnt;
}

signed main()
{
    in(n);in(m);
    for(R int i=1;i<=n;i++)in(c[i]);
    for(R int i=1,x,y;i<n;i++)
    {
        in(x),in(y);
        add(x,y);
        add(y,x);
    }
    dfs(1,0);build(1,1,n);
    for(R int i=1,opt,v,c;i<=m;i++)
    {
        in(opt);
        switch(opt)
        {
            case 1:in(v),in(c);change(1,1,n,dfn[v],dfn[v]+size[v]-1,c);break;
            case 2:in(v);printf("%lld\n",tquery(v));break;
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/-guz/p/9901528.html