zoukankan      html  css  js  c++  java
  • DFS序+线段树+bitset CF 620E New Year Tree(圣诞树)

    题目链接

    题意:

      一棵以1为根的树,树上每个节点有颜色标记(<=60),有两种操作:

      1. 可以把某个节点的子树的节点(包括本身)都改成某种颜色

      2. 查询某个节点的子树上(包括本身)有多少个不同的颜色

    思路:

      和2012年多校第7场的G题是同类题,DFS序处理出每个节点管辖的管辖范围[L[u], R[u]],其中L[u]就是子树根节点u所在的位置,用线段树成端更新颜色变化,注意到颜色(<=60),可以用bitset<60>,0表示没有这个颜色,1表示有,异或就能区间合并,最后count一下不同颜色的个数。

    另外:

      以前这种题是做不了的,现在都能秒掉了,说明在进步:)

    #include <bits/stdc++.h>
    
    const int N = 4e5 + 5;
    int a[N];
    std::vector<int> edge[N];
    int L[N], R[N], id[N];
    int tim;
    
    #define lson l, mid, o << 1
    #define rson mid + 1, r, o << 1 | 1
    struct Node {
        std::bitset<60> color;
        int lazy;
    };
    Node node[N<<2];
    
    void push_up(int o) {
        node[o].color = node[o<<1].color | node[o<<1|1].color;
    }
    
    void push_down(int o) {
        if (node[o].lazy != -1) {
            node[o<<1].lazy = node[o<<1|1].lazy = node[o].lazy;
            node[o<<1].color.reset ();
            node[o<<1].color.set (node[o].lazy);
            node[o<<1|1].color.reset ();
            node[o<<1|1].color.set (node[o].lazy);
            node[o].lazy = -1;
        }
    }
    
    void build(int l, int r, int o) {
        node[o].lazy = -1;
        node[o].color.reset ();  //clear to 0
        if (l == r) {
            node[o].color.set (a[id[l]]);  //set to 1
            return ;
        }
        int mid = l + r >> 1;
        build (lson);
        build (rson);
        push_up (o);
    }
    
    void updata(int ql, int qr, int c, int l, int r, int o) {
        if (ql <= l && r <= qr) {
            node[o].lazy = c;
            node[o].color.reset ();
            node[o].color.set (c);
            return ;
        }
        push_down (o);
        int mid = l + r >> 1;
        if (ql <= mid) {
            updata (ql, qr, c, lson);
        }
        if (qr > mid) {
            updata (ql, qr, c, rson);
        }
        push_up (o);
    }
    
    std::bitset<60> query(int ql, int qr, int l, int r, int o) {
        if (ql <= l && r <= qr) {
            return node[o].color;
        }
        push_down (o);
        int mid = l + r >> 1;
        std::bitset<60> ret;
        if (ql <= mid) {
            ret |= query (ql, qr, lson);
        }
        if (qr > mid) {
            ret |= query (ql, qr, rson);
        }
        return ret;
    }
    
    void DFS(int u, int fa) {
        L[u] = ++tim; id[tim] = u;
        for (auto v: edge[u]) {
            if (v != fa) {
                DFS (v, u);
            }
        }
        R[u] = tim;
    }
    
    int main() {
        int n, m;
        scanf ("%d%d", &n, &m);
        for (int i=1; i<=n; ++i) {
            scanf ("%d", a+i);
            a[i]--;
        }
        for (int i=1; i<n; ++i) {
            int x, y;
            scanf ("%d%d", &x, &y);
            edge[x].push_back (y);
            edge[y].push_back (x);
        }
        tim = 0;
        DFS (1, 0);
        build (1, tim, 1);
    
        for (int i=0; i<m; ++i) {
            int type, v;
            scanf ("%d%d", &type, &v);
            if (type == 1) {
                int c;
                scanf ("%d", &c);
                c--;
                updata (L[v], R[v], c, 1, tim, 1);
            } else {
                std::bitset<60> ans = query (L[v], R[v], 1, tim, 1);
                printf ("%d
    ", ans.count ());
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    (二)数据源处理2-xlrd操作excel
    (二)数据源处理1-configparser读取.ini配置文件
    数据源处理概述(二)
    接口自动化框架概述(一)
    git文件操作
    git分支管理
    git标签管理
    Monkey
    adb命令大全
    Springboot使用AOP实现统一处理Web请求日志
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5659474.html
Copyright © 2011-2022 走看看