zoukankan      html  css  js  c++  java
  • 【CF620E】New Year Tree

    (题面来自luogu)

    题意翻译

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

    有两种操作:

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

    2 v 查询以v为根的子树中的节点有多少种不同的颜色
    翻译贡献者UID:28455

    n、m <= 4e5,ci <= 60。

      今天唯一听懂的一道题目,调了两个小时……因为要查询子树信息,考虑构造出dfs序之后,用线段树维护区间颜色。因为颜色只有60种,可以维护在节点上维护bitset或者一个64位整型来压缩状态,每一位上表示以该点为根的子树内是否含有这个颜色。

      线段树内的tag是不可以累加的,每个tag都是一次直接修改,因此要在下推时特判掉空的无效标记。

    代码:

    1. #include <bitset>  
    2. #include <cstdio>  
    3. #include <iostream>  
    4. #define maxn 400010  
    5. using namespace std;  
    6. template <typename T>  
    7. void read(T &x) {  
    8.     x = 0;  
    9.     int f = 1;  
    10.     char ch = getchar();  
    11.     while (!isdigit(ch)) {  
    12.         if (ch == '-')  
    13.             f = -1;  
    14.         ch = getchar();  
    15.     }  
    16.     while (isdigit(ch)) {  
    17.         x = x * 10 + (ch ^ 48);  
    18.         ch = getchar();  
    19.     }  
    20.     x *= f;  
    21.     return;  
    22. }  
    23. int n, m;  
    24. struct E {  
    25.     int to, nxt;  
    26. } edge[maxn << 1];  
    27. int head[maxn], top;  
    28. inline void insert(int u, int v) {  
    29.     edge[++top] = (E) {v, head[u]};  
    30.     head[u] = top;  
    31. }  
    32. int color[maxn], val[maxn], dfn[maxn], size[maxn], tmr;  
    33. void dfs(int u, int pre) {  
    34.     dfn[u] = ++tmr;  
    35.     size[u] = 1;  
    36.     val[tmr] = color[u];  
    37.     for (int i = head[u]; i; i = edge[i].nxt) {  
    38.         int v = edge[i].to;  
    39.         if (v != pre) {  
    40.             dfs(v, u);  
    41.             size[u] += size[v];  
    42.         }  
    43.     }  
    44. }  
    45.   
    46. namespace Segment_tree {  
    47.     #define lc (nd<<1)  
    48.     #define rc ((nd<<1)|1)  
    49.     #define mid ((l + r) >> 1)  
    50.     bitset<61> seg[maxn << 2];  
    51.     bitset<61> tag[maxn << 2];  
    52.     inline void put_tag(int nd, bitset<61> op) {  
    53.         if (op.count()) //关键,以及第一个调炸的点   
    54.             seg[nd] = op,  
    55.             tag[nd] = op;  
    56.     }  
    57.     inline void push_down(int nd) {  
    58.         put_tag(lc, tag[nd]);  
    59.         put_tag(rc, tag[nd]);  
    60.         tag[nd].reset();//第二个调炸的点:忘记清除标记   
    61.     }  
    62.     inline void update(int nd) {  
    63.         seg[nd] = seg[lc] | seg[rc];  
    64.     }  
    65.     void build(int nd, int l, int r) {  
    66.         if (l == r) {  
    67.             seg[nd].set(val[l], 1);   
    68.             return;  
    69.         }  
    70.         build(lc, l, mid);  
    71.         build(rc, mid + 1, r);  
    72.         update(nd);  
    73.     }  
    74.     void modify(int nd, int l, int r, int ql, int qr, bitset<61> op) {  
    75.         if (l >= ql && r <= qr) {  
    76.             put_tag(nd, op);  
    77.             return;  
    78.         } else if (l > qr || r < ql)  
    79.             return;  
    80.         push_down(nd);  
    81.         modify(lc, l, mid, ql, qr, op);  
    82.         modify(rc, mid + 1, r, ql, qr, op);  
    83.         update(nd);  
    84.     }  
    85.     bitset<61> query(int nd, int l, int r, int ql, int qr) {  
    86.         if (l >= ql && r <= qr)  
    87.             return seg[nd];  
    88.         if (l > qr || r < ql) {  
    89.             bitset<61> t;  
    90.             return t;  
    91.         }  
    92.         push_down(nd);  
    93.         return query(lc, l, mid, ql, qr) | query(rc, mid + 1, r, ql, qr);  
    94.     }  
    95. using namespace Segment_tree;  
    96. int main() {  
    97.     read(n), read(m);  
    98.     for (int i = 1; i <= n; ++i)  
    99.         read(color[i]);  
    100.     int u, v, t, k;  
    101.     for (int i = 1; i < n; ++i) {  
    102.         read(u), read(v);  
    103.         insert(u, v), insert(v, u);  
    104.     }  
    105.     dfs(1, 0);  
    106.     build(1, 1, n);  
    107.     bitset<61> op;  
    108.     for (int i = 1; i <= m; ++i) {  
    109.         read(t), read(v);  
    110.         if (t == 1) {  
    111.             read(k);  
    112.             op.reset();  
    113.             op.set(k, 1);  
    114.             modify(1, 1, n, dfn[v], dfn[v] + size[v] - 1, op);  
    115.         } else {  
    116.             op = query(1, 1, n, dfn[v], dfn[v] + size[v] - 1);  
    117.             printf("%d ", op.count());  
    118.         }  
    119.     }  
    120.     return 0;  
    121. }  
  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/TY02/p/11215587.html
Copyright © 2011-2022 走看看