(题面来自luogu)

题意翻译

一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和。

ci <= n <= 1e5

  裸题。统计时先扫一遍得到出现次数最大值,然后再扫一遍看哪个颜色的出现次数与mxCnt相等。注意用一个bool数组判重,清空轻儿子贡献时要顺手把bool数组也打成false。(这是错的,请看下一份代码)

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cctype>
  4. #define maxn 100010
  5. using namespace std;
  6. template <typename T>
  7. void read(T &x) {
  8. x = 0;
  9. char ch = getchar();
  10. while (!isdigit(ch))
  11. ch = getchar();
  12. while (isdigit(ch))
  13. x = x * 10 + (ch ^ 48), ch = getchar();
  14. }
  15. int n;
  16. int head[maxn], top;
  17. struct E {
  18. int to, nxt;
  19. } edge[maxn << 1];
  20. inline void insert(int u, int v) {
  21. edge[++top] = (E) {v, head[u]};
  22. head[u] = top;
  23. }
  24. int son[maxn], size[maxn];
  25. long long ans[maxn];
  26. void dfs1(int u, int pre) {
  27. size[u] = 1;
  28. for (int i = head[u]; i; i = edge[i].nxt) {
  29. int v = edge[i].to;
  30. if (v == pre) continue;
  31. dfs1(v, u);
  32. size[u] += size[v];
  33. if (size[v] > size[son[u]])
  34. son[u] = v;
  35. }
  36. return;
  37. }
  38. int color[maxn], cnt[maxn], sum;
  39. int curSon, mxCnt;
  40. bool vis[maxn];
  41. void calc(int u, int pre, bool op) {
  42. op ? (++cnt[color[u]], mxCnt = max(mxCnt, cnt[color[u]])) : (--cnt[color[u]], vis[color[u]] = false);
  43. for (int i = head[u]; i; i = edge[i].nxt) {
  44. int v = edge[i].to;
  45. if (v == pre || v == curSon)
  46. continue;
  47. calc(v, u, op);
  48. }
  49. }
  50. void stats(int u, int pre) {
  51. if (cnt[color[u]] == mxCnt && !vis[color[u]])
  52. sum += color[u], vis[color[u]] = true;
  53. for (int i = head[u]; i; i = edge[i].nxt) {
  54. int v = edge[i].to;
  55. if (v != pre)
  56. stats(v, u);
  57. }
  58. return;
  59. }
  60. void dsu(int u, int pre, bool op) {
  61. for (int i = head[u]; i; i = edge[i].nxt) {
  62. int v = edge[i].to;
  63. if (v == pre || v == son[u])
  64. continue;
  65. dsu(v, u, 0);
  66. }
  67. if (son[u])
  68. dsu(son[u], u, 1), curSon = son[u];
  69. mxCnt = 0;
  70. calc(u, pre, 1);
  71. stats(u, pre);
  72. ans[u] = sum;
  73. curSon = 0;
  74. if (!op) {
  75. sum = 0;
  76. calc(u, pre, 0);
  77. }
  78. }
  79. int main() {
  80. read(n);
  81. for (int i = 1; i <= n; ++i)
  82. read(color[i]);
  83. int u, v;
  84. for (int i = 1; i < n; ++i) {
  85. read(u), read(v);
  86. insert(v, u), insert(u, v);
  87. }
  88. dfs1(1, 0);
  89. dsu(1, 0, 1);
  90. for (int i = 1; i <= n; ++i)
  91. printf("%I64d ", ans[i]);
  92. return 0;
  93. }

   (交这个题的时候cf炸了……才不是因为我TLE呢

--------------------------

  然而果然出了锅,昨天CF评测机大概是被这个弱智错误笑死的……

  重测了下,上面那份代码是错的,原因是没有考虑重儿子内的最大出现次数。然而原思路越改越复杂,后来想了想,每遍历到重复的颜色其出现次数都会+1,因此不用判重,从每个点统计时扫一遍就好了。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cctype>
  4. #define maxn 100010
  5. using namespace std;
  6. template <typename T>
  7. void read(T &x) {
  8. x = 0;
  9. char ch = getchar();
  10. while (!isdigit(ch))
  11. ch = getchar();
  12. while (isdigit(ch))
  13. x = x * 10 + (ch ^ 48), ch = getchar();
  14. }
  15. int n;
  16. int head[maxn], top;
  17. struct E {
  18. int to, nxt;
  19. } edge[maxn << 1];
  20. inline void insert(int u, int v) {
  21. edge[++top] = (E) {v, head[u]};
  22. head[u] = top;
  23. }
  24. int son[maxn], size[maxn];
  25. long long ans[maxn];
  26. void dfs1(int u, int pre) {
  27. size[u] = 1;
  28. for (int i = head[u]; i; i = edge[i].nxt) {
  29. int v = edge[i].to;
  30. if (v == pre) continue;
  31. dfs1(v, u);
  32. size[u] += size[v];
  33. if (size[v] > size[son[u]])
  34. son[u] = v;
  35. }
  36. return;
  37. }
  38. int color[maxn], cnt[maxn];
  39. long long sum;
  40. int curSon, mxCnt;
  41. void calc(int u, int pre, int val) {
  42. cnt[color[u]] += val;
  43. if (val == 1) {
  44. if (cnt[color[u]] > mxCnt)
  45. mxCnt = cnt[color[u]], sum = color[u];
  46. else if (cnt[color[u]] == mxCnt)
  47. sum += color[u];
  48. }
  49. for (int i = head[u]; i; i = edge[i].nxt) {
  50. int v = edge[i].to;
  51. if (v == pre || v == curSon)
  52. continue;
  53. calc(v, u, val);
  54. }
  55. }
  56. void dsu(int u, int pre, bool op) {
  57. for (int i = head[u]; i; i = edge[i].nxt) {
  58. int v = edge[i].to;
  59. if (v == pre || v == son[u])
  60. continue;
  61. dsu(v, u, 0);
  62. }
  63. if (son[u])
  64. dsu(son[u], u, 1), curSon = son[u];
  65. calc(u, pre, 1);
  66. ans[u] = sum;
  67. curSon = 0;
  68. if (!op) {
  69. mxCnt = sum = 0;
  70. calc(u, pre, -1);
  71. }
  72. }
  73. int main() {
  74. read(n);
  75. for (int i = 1; i <= n; ++i)
  76. read(color[i]);
  77. int u, v;
  78. for (int i = 1; i < n; ++i) {
  79. read(u), read(v);
  80. insert(v, u), insert(u, v);
  81. }
  82. dfs1(1, 0);
  83. dsu(1, 0, 1);
  84. for (int i = 1; i <= n; ++i)
  85. printf("%I64d ", ans[i]);
  86. return 0;
  87. }

【CF600E】Lomsat gelral——树上启发式合并的更多相关文章

  1. CF600E Lomsat gelral 树上启发式合并

    题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\)​. 如果一种颜色在以 \(x\) ...

  2. CF EDU - E. Lomsat gelral 树上启发式合并

    学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...

  3. CF 600 E Lomsat gelral —— 树上启发式合并

    题目:http://codeforces.com/contest/600/problem/E 看博客:https://blog.csdn.net/blue_kid/article/details/82 ...

  4. CF600E Lomsat gelral——线段树合并/dsu on tree

    题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...

  5. Codeforces 600 E. Lomsat gelral (dfs启发式合并map)

    题目链接:http://codeforces.com/contest/600/problem/E 给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少. 最容 ...

  6. CF600E:Lomsat gelral(线段树合并)

    Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...

  7. 【学习笔记/题解】树上启发式合并/CF600E Lomsat gelral

    题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. ...

  8. Codeforces 600E - Lomsat gelral(树上启发式合并)

    600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...

  9. [Codeforces600E] Lomsat gelral(树上启发式合并)

    [Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...

随机推荐

  1. postMessage 跨域

    基于 postMessage 和 localStorage 的跨域本地存储方案 安·记 2014-09-07 2099 阅读 跨域 存储 localStorage HTML5 的 postMessag ...

  2. modbus协议开关量采集模块

    modbus协议开关量采集模块是指的使用Modbus协议的进行信号的采集与控制的一种设备. Modbus 协议设备都具有唯一的 Modbus 地址,众山 DTU 默认 Modbus 地址为 100,用 ...

  3. 在充电桩联网部署方案中4G DTU的优势是什么

    充电桩作为电动汽车充电生态链的一环,具有非常重要的作用,成都远向电子为电动车充电桩.充电站提供专业的无线通信组网产品与技术解决方案,协助充电桩厂家.充电桩运营商.商业充电服务商实现:充电桩设备工作状态 ...

  4. 容器探针(liveness and readiness probe)

    一.为什么需要容器探针 如何保持Pod健康   只要将pod调度到某个节点,Kubelet就会运行pod的容器,如果该pod的容器有一个或者所有的都终止运行(容器的主进程崩溃),Kubelet将重启容 ...

  5. From delete library to run の 初见Django篇

    一.虚拟环境简介 1.什么是虚拟环境? 虚拟环境是用于依赖项管理和项目隔离的python工具,允许python的第三方库安装在本地特定项目的隔离目录中,而不是全局安装. 2.虚拟环境的组成 ① 安装了 ...

  6. ssh 和scp 非22端口

    ssh :(命令中的 p 小写) ssh -p 端口号 root@服务器ip scp: (命令中的 P 大写)(-r表示将目录下的目录递归拷贝.".*"是将所有文件包括隐藏文件.) ...

  7. net core webapi多版本控制与swagger(nswag)配置

    前言 首先希望webapi 支持多版本,swagger针对不同的版本可进行交互.多版本控制基于Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer 包,swa ...

  8. simulink产生周期矩形波和8421码

    初次入门simulink,由于学习了数字逻辑,试图进行仿真,首先需要的就是8421码,但是没找到simulink里面相关模块,如果各位知道怎么弄可以评论告诉我分享分享哈哈 我用的是matlab2016 ...

  9. leetcode两数之和go语言

    两数之和(Go语言) 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复 ...

  10. c#连接mysql答题步骤

    引用mysql数据库 using MySql.Data.MySqlClient; 有一个mysql.dll文件 下面是实例化连接数据库 MySqlConnection Conn = new MySql ...