(题面来自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. 【总结】IP

    一. IP基本认识 1.IP 在 TCP/IP 参考模型中处于第三层,也就是网络层. 网络层的主要作用是:实现主机与主机之间的通信,也叫点对点(end to end)通信 2.网络层与数据链路层有什么 ...

  2. 怎么提高selenium脚本的自动化执行效率?

    1.使用配置更高的电脑,选择更快的网络环境:2.使用效率更高的语言,比如 java 比 python,这种方案可行性不高:3.能直接访问网址的,就不要一步一步点击:4.不要盲目增加 sleep,尽量使 ...

  3. lora传输模块的特点概述

    现今Lora已经是一种在物联网中广泛应用的技术,它是一种无线调制的方式,相对于传统的FSK调制技术来说,Lora在抑制同频干扰方面有非常大的优势,它解决了无法同时兼顾距离.抗扰和功耗不足的问题;另外l ...

  4. 分布式文档存储数据库之MongoDB基础入门

    一.MongoDB简介 MongoDB是用c++语言开发的一款易扩展,易伸缩,高性能,开源的,schema free 的基于文档的nosql数据库:所谓nosql是指不仅仅是sql的意思,它拥有部分s ...

  5. 面试 之 nginx,负载,动静分离

    大家先看这个逻辑图 为什么我们要这样去架构我们的一个项目呢? 这样做的话,动态请求要先访问 A,A 转发访问 B,再由 B 返回结果给 A,A 最后又将结果返回给客户端这样是不是很麻烦? 最初开发的时 ...

  6. 利用MultipartFile来进行文件上传

    这个例子实在SpringMVC的基础上完成的,因此在web.xml中需要配置 web.xml <!-- 配置Spring MVC的入口 DispatcherServlet,把所有的请求都提交到该 ...

  7. efcore 学习

    新开一个博客来写一下ef core的学习过程 这个博客内容会跟着官网走 具体可见官网https://docs.microsoft.com/zh-cn/ef/core/get-started/?tabs ...

  8. 利用Kotlin扩展函数实现任意View的点击处理(点击效果和防止快速点击)

    利用Kotlin扩展函数实现View的点击处理(点击效果和防止快速点击) kotlin经典写法: view?.setOnClickListener { //实现 } 项目实践证明,这种写法存在问题 例 ...

  9. js给多级复杂动态变量赋值

    1 function SetVal(field, val) { 2 var arr = field.split("."); 3 var str = arr[0]; 4 if (wi ...

  10. 使用css控制table的cellspacing和cellpadding属性

    HTML默认的表格样式之间有间隙,每次为了解决这些问题,总要在table标签里添加cellspacing和cellpadding,你是否也很厌倦这样的写法, 那么有没有对应的CSS属性能达到相同的效果 ...