New Year Tree CodeForces -620E

这个题有一个技巧:把颜色压到一个long long 上。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
LL lft[62],c[400100];
vector<int> e[400100];
int n,m;
int pp[400100],lp[400100],rp[400100],len;
void dfs(int u,int fa)
{
    pp[++len]=u;lp[u]=len;
    for(auto& v:e[u])
        if(v!=fa)
            dfs(v,u);
    rp[u]=len;
}
#define mid ((l+r)>>1)
#define lc (num<<1)
#define rc (num<<1|1)
LL dat[1600010],setv[1600010];
void build(int l,int r,int num)
{
    setv[num]=-1;
    if(l==r)    {dat[num]=c[pp[l]];return;}
    build(l,mid,lc);build(mid+1,r,rc);
    dat[num]=dat[lc]|dat[rc];
}
int L,R;LL x;
void pd(int l,int r,int num)
{
    if(setv[num]!=-1)
    {
        dat[lc]=setv[num];dat[rc]=setv[num];
        setv[lc]=setv[num];setv[rc]=setv[num];
        setv[num]=-1;
    }
}
void change(int l,int r,int num)
{
    if(L<=l&&r<=R)    {dat[num]=x;setv[num]=x;return;}
    pd(l,r,num);
    if(L<=mid)    change(l,mid,lc);
    if(mid<R)    change(mid+1,r,rc);
    dat[num]=dat[lc]|dat[rc];
}
LL query(int l,int r,int num)
{
    if(L<=l&&r<=R)    return dat[num];
    pd(l,r,num);
    LL ans=0;
    if(L<=mid)    ans|=query(l,mid,lc);
    if(mid<R)    ans|=query(mid+1,r,rc);
    return ans;
}
int main()
{
    int i,a,b,v,idx;
    lft[0]=1;
    for(i=1;i<=61;i++)    lft[i]=lft[i-1]<<1;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)    scanf("%lld",&c[i]),c[i]=lft[c[i]];
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        e[a].push_back(b);e[b].push_back(a);
    }
    dfs(1,0);
    build(1,n,1);
    while(m--)
    {
        scanf("%d",&idx);
        if(idx==1)
        {
            scanf("%d%lld",&v,&x);x=lft[x];
            L=lp[v];R=rp[v];change(1,n,1);
        }
        else if(idx==2)
        {
            scanf("%d",&v);L=lp[v];R=rp[v];
            printf("%d\n",__builtin_popcountll(query(1,n,1)));
        }
    }
    return 0;
}

 

posted @ 2018-04-04 08:08  hehe_54321  阅读(186)  评论(0编辑  收藏  举报
AmazingCounters.com