(题面来自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. namespace Segment_tree {
  46. #define lc (nd<<1)
  47. #define rc ((nd<<1)|1)
  48. #define mid ((l + r) >> 1)
  49. bitset<61> seg[maxn << 2];
  50. bitset<61> tag[maxn << 2];
  51. inline void put_tag(int nd, bitset<61> op) {
  52. if (op.count()) //关键,以及第一个调炸的点
  53. seg[nd] = op,
  54. tag[nd] = op;
  55. }
  56. inline void push_down(int nd) {
  57. put_tag(lc, tag[nd]);
  58. put_tag(rc, tag[nd]);
  59. tag[nd].reset();//第二个调炸的点:忘记清除标记
  60. }
  61. inline void update(int nd) {
  62. seg[nd] = seg[lc] | seg[rc];
  63. }
  64. void build(int nd, int l, int r) {
  65. if (l == r) {
  66. seg[nd].set(val[l], 1);
  67. return;
  68. }
  69. build(lc, l, mid);
  70. build(rc, mid + 1, r);
  71. update(nd);
  72. }
  73. void modify(int nd, int l, int r, int ql, int qr, bitset<61> op) {
  74. if (l >= ql && r <= qr) {
  75. put_tag(nd, op);
  76. return;
  77. } else if (l > qr || r < ql)
  78. return;
  79. push_down(nd);
  80. modify(lc, l, mid, ql, qr, op);
  81. modify(rc, mid + 1, r, ql, qr, op);
  82. update(nd);
  83. }
  84. bitset<61> query(int nd, int l, int r, int ql, int qr) {
  85. if (l >= ql && r <= qr)
  86. return seg[nd];
  87. if (l > qr || r < ql) {
  88. bitset<61> t;
  89. return t;
  90. }
  91. push_down(nd);
  92. return query(lc, l, mid, ql, qr) | query(rc, mid + 1, r, ql, qr);
  93. }
  94. } using namespace Segment_tree;
  95. int main() {
  96. read(n), read(m);
  97. for (int i = 1; i <= n; ++i)
  98. read(color[i]);
  99. int u, v, t, k;
  100. for (int i = 1; i < n; ++i) {
  101. read(u), read(v);
  102. insert(u, v), insert(v, u);
  103. }
  104. dfs(1, 0);
  105. build(1, 1, n);
  106. bitset<61> op;
  107. for (int i = 1; i <= m; ++i) {
  108. read(t), read(v);
  109. if (t == 1) {
  110. read(k);
  111. op.reset();
  112. op.set(k, 1);
  113. modify(1, 1, n, dfn[v], dfn[v] + size[v] - 1, op);
  114. } else {
  115. op = query(1, 1, n, dfn[v], dfn[v] + size[v] - 1);
  116. printf("%d\n", op.count());
  117. }
  118. }
  119. return 0;
  120. }

【CF620E】New Year Tree的更多相关文章

  1. 线段树+Dfs序【CF620E】New Year Tree

    Description 你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]. 有两种操作: 1 v c 将以v为根的子树中所有点颜色更改为c 2 v 查询以v为根的子树中的节点有多少种 ...

  2. 【数据结构】B-Tree, B+Tree, B*树介绍 转

    [数据结构]B-Tree, B+Tree, B*树介绍 [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tre ...

  3. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  4. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

  5. AC日记——【模板】Link Cut Tree 洛谷 P3690

    [模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...

  6. LG3690 【模板】Link Cut Tree 和 SDOI2008 洞穴勘测

    UPD:更新了写法. [模板]Link Cut Tree 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 后接两个整数(x,y),代表询问从x到y ...

  7. (RE) luogu P3690 【模板】Link Cut Tree

    二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...

  8. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  9. 【LeetCode】199. Binary Tree Right Side View 解题报告(Python)

    [LeetCode]199. Binary Tree Right Side View 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/probl ...

随机推荐

  1. Libevent库基础(1)

    1.创建 eevent_base struct event_base *base = event_base_new(); 2.创建 事件event struct event *ev; struct e ...

  2. 1. HttpRunner介绍及环境准备

    介绍 HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架 只需编写维护一份 YAML/JSON脚本,即可实现自动化测试.性能测试.线上监控.持续集成等多种测试需求 官方文档: htt ...

  3. 基于虚拟机安装Linux并利用LVM创建磁盘分区

    主要步骤:将磁盘设置为LVM类型,并在这四个分区上创建物理卷.卷组和逻辑卷,最后将逻辑卷挂载.电脑使用Windows10 企业版 LTSC 操作系统.虚拟机使用VMware15.5 pro . 1.安 ...

  4. Loading descriptor for XXX.'has encountered a problem' A internal error occured during:"Loading ....."

    在JavaWeb部署Tomcat后启动Jsp发现这样的报错 这可能是Tomcat的运行欢迎有问题,按下图所示打开Tomcat界面.Servers目录就是当前工作空间对所有工程适用的的Tomcat环境, ...

  5. ant-design-vue 快速避坑指南

    ant-design-vue是蚂蚁金服 Ant Design 官方唯一推荐的Vue版UI组件库,它其实是Ant Design的Vue实现,组件的风格与Ant Design保持同步,组件的html结构和 ...

  6. inno steup 安装判断 进程是否运行

    1.添加了卸载判断用语 2.添加了安装程序进程是否存在使用了wmi服务 ; 脚本由 Inno Setup 脚本向导 生成! ; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档! #d ...

  7. 自制 os 极简教程1:写一个操作系统有多难

    为什么叫极简教程呢?听我慢慢说 不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了 ...

  8. .NET5都来了,你还不知道怎么部署到linux?最全部署方案,总有一款适合你

    随着2020进入4季度,.NET5正式版也已经与大家见面了.不过,尽管 .NET Core发布已经有四五年的时间,但到目前为止,依旧有很多.NET开发者在坚守者.NET4,原因不尽相同,但最大的问题可 ...

  9. Spring Boot 2.4.0 正式发布!全新的配置处理机制,拥抱云原生!

    2020年11月12日,Spring官方发布了Spring Boot 2.4.0 GA的公告. 在这个版本中增加了大量的新特性和改进,下面我们一起看看在这个重要版本中都有哪些值得关注的内容! 更新内容 ...

  10. Netlink 内核实现分析 2

    netlink 应用层如何创建socket 应用层通过socket()系统调用创建Netlink套接字,socket系统调用的第一个参数可以是AF_NETLINK或PF_NETLINK(在Linux系 ...