• CodeForces 620E New Year Tree


    线段树+位运算

    首先对树进行DFS,写出DFS序列,记录下每一个节点控制的区间范围。然后就是区间更新和区间查询了。

    某段区间的颜色种类可以用位运算来表示,方便计算。

    如果仅有第i种颜色,那么就用十进制数(1<<i)表示。

    如果A区间有的颜色是col1,B区间有的颜色是col2,合并之后有的就是(col1 | col2)

    输出有几种,就是看得到的十进制数的二进制表示中有多少位是1.

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=4*100000+10;
    int n,q;
    int col[maxn];
    vector<int> Tree[maxn];
    bool b[maxn];
    int Left[maxn],Right[maxn];
    int s[2*maxn];
    int time;
    long long ans;
    struct SegTree
    {
        bool flag;
        long long ans;
    }segTree[2*maxn*4];
    
    void dfs(int now)
    {
        b[now]=1;
        Left[now]=(++time);
        s[time]=now;
        for(int i=0;i<Tree[now].size();i++)
            if(b[Tree[now][i]]==0)
                dfs(Tree[now][i]);
        Right[now]=(++time);
        s[time]=now;
    }
    
    void pushUp(int rt)
    {
        segTree[rt].ans=(segTree[2*rt].ans|segTree[2*rt+1].ans);
    }
    
    void pushDown(int rt)
    {
        if(segTree[rt].flag!=0)
        {
            segTree[2*rt].flag=segTree[2*rt+1].flag=segTree[rt].flag;
            segTree[2*rt].ans=segTree[2*rt+1].ans=segTree[rt].ans;
            segTree[rt].flag=0;
        }
    }
    
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            segTree[rt].flag=0;
            segTree[rt].ans=(long long)1<<((long long)col[s[l]]);
            return ;
        }
        int m=(l+r)/2;
        if(l<=m) build(l,m,2*rt);
        if(r>m) build(m+1,r,2*rt+1);
        pushUp(rt);
        return;
    }
    
    void quary(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            ans=(ans|segTree[rt].ans);
            return;
        }
        pushDown(rt);
        int m=(l+r)/2;
        if(L<=m) quary(L,R,l,m,2*rt);
        if(R>m) quary(L,R,m+1,r,2*rt+1);
        pushUp(rt);
        return;
    }
    
    void update(int info,int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            segTree[rt].flag=info;
            segTree[rt].ans=(long long)1<<(long long) info;
            return;
        }
    
        pushDown(rt);
        int m=(l+r)/2;
        if(L<=m) update(info,L,R,l,m,2*rt);
        if(R>m) update(info,L,R,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) scanf("%d",&col[i]);
        for(int i=0;i<=n;i++) Tree[i].clear();
        for(int i=1;i<=n-1;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            Tree[x].push_back(y);
            Tree[y].push_back(x);
        }
        memset(b,0,sizeof b);
        time=0,dfs(1);
        build(1,2*n,1);
        for(int i=1;i<=q;i++)
        {
            int tk;
            scanf("%d",&tk);
            if(tk==1)
            {
                int vk,ck;
                scanf("%d%d",&vk,&ck);
                update(ck,Left[vk],Right[vk],1,2*n,1);
            }
            else
            {
                int vk;
                scanf("%d",&vk);
                ans=0;
                quary(Left[vk],Right[vk],1,2*n,1);
                int num=0;
                while(ans)
                {
                    if(ans%2==1) num++;
                    ans=ans/2;
                }
                printf("%d
    ",num);
            }
        }
        return 0;
    }
  • 相关阅读:
    布隆过滤器
    string.ToString("X")的含义,转换为16进制
    Stream.Write()和Stream.Read(), Stream.Flush的作用,待学习
    linux查看CPU,内存使用情况
    HttpContext.Current.Request.InputStream
    程序员常去的10个顶级开发社区
    JavaScript 对象初探
    PHP – 架構設計 Data Access Layer 篇
    如何用 JavaScript 动态呼叫函数
    PHP – EasyUI DataGrid 资料存的方式
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5151188.html
Copyright © 2020-2023  润新知