zoukankan      html  css  js  c++  java
  • New Year Tree 【DFS序+线段树区间查询修改+二进制保存状态】

    题目链接【http://codeforces.com/problemset/problem/620/E】

    题意:给出n个数,每个数有一个初始的颜色。由这n个数组成一颗树。有两种操作1、将以节点u为根的子树的颜色染成k色。2、输出以节点u为根的子树的颜色总数。颜色有60种。

    题解:1、用DFS重新对这棵树编号in[u],out[u]表示以节点u为根的子树的区间左右端点。2、用线段树维护更新与查询。3、颜色保存:se每一个二进制位表示一种颜色。0表示没有这种颜色,反之有。

    因为有60种颜色,要用LL保存颜色。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e6+5;
    vector<int> v[maxn];
    int in[maxn],out[maxn];
    LL c[maxn];
    int n,m;
    int id;
    void DFS_ORDER(int u)
    {
        in[u] = ++id;
        for(int i = 0;i < v[u].size();i++)
        {
            int w = v[u][i];
            if(!in[w])    DFS_ORDER(w);
        }
        out[u] = id;
    }
    LL E[maxn*4],T[maxn*4];//值数组,标记数组
    void update(int id,int l,int r,int In,int Out,LL val)
    {
        if(r < In || l > Out)//不重合
            return ;
        if(l >= In && Out >= r)//包含
        {
            E[id] = val;
            T[id] = val;
            return ;
        }
        if(T[id])//相交
        {
            int mid = (l+r)>>1;
            T[id << 1] = T[id];
            E[id << 1] = T[id];
            T[id << 1 | 1] = T[id];
            E[id << 1 | 1] = T[id];
            T[id] = 0;//取消标记
        }
        int mid = (l+r) >>1;
        update(id<<1,l,mid,In,Out,val);
        update(id<<1|1,mid+1,r,In,Out,val);
        E[id] = E[id<<1]|E[id<<1|1];
    }
    LL query(int id,int l,int r,int In,int Out)
    {
        if(r < In || l > Out)//不重合
            return 0;
        if(l >= In && Out >= r)//包含
            return E[id];
        if(T[id])//相交
        {
            int mid = (l+r)>>1;
            T[id << 1] = T[id];
            E[id << 1] = T[id];
            T[id << 1 | 1] = T[id];
            E[id << 1 | 1] = T[id];
            T[id] = 0;//取消标记
        }
        int mid = (l+r) >>1;
        LL ans1 = query(id<<1,l,mid,In,Out);
        LL ans2 = query(id<<1|1,mid+1,r,In,Out);
        return ans1|ans2;
    }
    int main ()
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++)
            scanf("%lld", &c[i]);
        for(int i = 1;i <= n-1;i++)
        {
            int u,w;
            scanf("%d%d",&u,&w);
            v[u].push_back( w );
            v[w].push_back( u );
        }
        DFS_ORDER(1);
        for(int i = 1;i <= n;i++)
        {
            LL x = LL(1)<<(c[i]-1);
            update(1,1,n,in[i],in[i],x);
        }
        int ty,u;LL val;
        for(int i = 1;i <= m;i++)
        {
            scanf("%d",&ty);
            if(ty == 1)
            {
                scanf("%d%lld",&u,&val);
                LL x = LL(1)<<(val-1);
                update(1,1,n,in[u],out[u],x);
            }
            else
            {
                scanf("%d",&u);
                LL t = query(1,1,n,in[u],out[u]);
                int ans=0;
                while(t){if(t&1)ans++;t>>=1;}
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    [那些你所不知道的鬼畜写法]数据结构小探
    索引
    数据类型
    存储引擎
    事务
    视图、触发器、存储过程、自定义函数
    约束
    数据库介绍
    线程基础、线程池
    操作系统基础
  • 原文地址:https://www.cnblogs.com/pealicx/p/6236111.html
Copyright © 2011-2022 走看看