Algorithm

名称:树上启发式合并, dsu on tree, 静态链分治

用处:一般用来解决一类不带修改子树查询问题

核心思想为:利用重链剖分的性质优化子树贡献的计算。

前置知识:启发式合并,最常见的就是并查集的按秩合并了,有带按秩合并的并查集中,对于两个大小不一样的集合,我们将小的集合合并到大的集合中,而不是将大的集合合并到小的集合中。让高度小的树成为高度较大的树的子树,这个优化可以称为启发式合并算法。

相关题目:

  1. 给出一棵 n 个节点以 1 为根的树,节点 u的颜色为 C[u],现在对于每个结点 u 询问 u 子树里一共出现了多少种不同的颜色。 n < 2e5
  2. 树的节点有颜色,一种颜色占领了一个子树,当且仅当没有其他颜色在这个子树中出现得比它多。求占领每个子树的所有颜色之和 CF600E
  3. 给一棵树,每个节点的权值是’a’ 到’v’ 的字母,每次询问要求在一个子树找一条路径,使该路径包含的字符排序后成为回文串。 CF741D
  4. UOJ284 快乐游戏鸡

Problem

树的节点有颜色,一种颜色占领了一个子树,当且仅当没有其他颜色在这个子树中出现得比它多。求占领每个子树的所有颜色之和 CF600E

solution

算法思路

  • 这道题我们可以遍历整棵树,并用一个cnt数组记录每种颜色出现几次

    但是每做完一棵子树就需要清空cnt,以免对其兄弟造成影响。

    而这样做它的祖先时就要把它重新搜一遍,浪费时间

    但是我们发现,对于每个节点x,最后一棵子树是不用清空的,因为做完那棵子树后可以把其结果直接加入x的答案中。

    选哪棵子树呢?当然是所含节点最多的一棵咯,我们称之为“重儿子”

  • 考虑暴力怎么写:遍历每个节点—>把子树中的所有颜色暴力统计出来更新答案—>消除该节点的贡献—继续递归这肯定是O(n^2)的。

  • dsu on tree巧妙的利用了轻重链剖分的性质,把复杂度降到了O(nlogn)。你不知道啥叫轻重链剖分?一句话:对于树上的一个点,与其相连的边中,连向的节点子树大小最大的边叫做重边,其他的边叫轻边

算法证明

  • 设根到该节点有x条轻边,该节点的大小为y,根据轻重边的定义,轻边所连向的点的大小不会成为该节点总大小的一半。这样每经过一条轻边,y的上限就会/2,因此y<n/2^x,是log的。即一个节点到根的路径上轻边个数不会超过logn条。所以最后的复杂度为O(nlogn)

算法实现,对于节点i:

  • 遍历每一个节点

    • 递归解决所有的轻儿子,同时消除递归产生的影响
  • 递归重儿子,不消除递归的影响
  • 统计所有轻儿子对答案的影响
  • 更新该节点的答案
  • 删除所有轻儿子对答案的影响
//题意:给出一棵 n 个结点的树,每个结点都有一种颜色编号,求该树中每棵子树里的出现次数最多的颜色的编号和。
//思路:dsu on tree,对树做轻重链剖分,先跑轻儿子,最后一遍跑重儿子的时候不用清空数组,复杂度降低为O(nlogn)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;LL c[maxn], ans[maxn];vector<int>G[maxn];
LL siz[maxn], son[maxn];
void dsu(int x, int fa){ //轻重链剖分siz[x] = 1;for(int to : G[x]){if(to==fa)continue;dsu(to,x);siz[x] += siz[to];if(siz[to]>siz[son[x]])son[x]=to;}
}LL cnt[maxn], tmp, tmpv, Son;
void add(int x, int fa, int val){//统计x节点的贡献cnt[c[x]] += val;if(cnt[c[x]]>tmpv)tmpv=cnt[c[x]],tmp=c[x];else if(cnt[c[x]]==tmpv)tmp +=c[x];for(int to : G[x]){if(to==fa)continue;if(to==Son)continue;//统计x节点的轻儿子时不统计重儿子add(to,x,val);}
}
void dfs(int x, int fa, int op){//遍历每个节点for(int to : G[x]){if(to==fa)continue;if(to!=son[x])dfs(to,x,0);//暴力统计轻边的贡献,op=0表示递归完成后消除对该点的影响}if(son[x])dfs(son[x],x,1), Son=son[x];//统计重儿子的贡献,不消除影响add(x,fa,1); Son=0;   //暴力统计所有轻儿子的贡献ans[x] = tmp;if(!op)add(x,fa,-1),tmp=0,tmpv=0;//消除对该点的影响
}int main(){ios::sync_with_stdio(false);int n;  cin>>n;for(int i = 1; i <= n; i++)cin>>c[i];for(int i = 1; i <= n-1; i++){int x, y;  cin>>x>>y;G[x].push_back(y);G[y].push_back(x);}dsu(1,0);dfs(1,0,0);for(int i = 1; i <= n; i++)cout<<ans[i]<<" ";return 0;
}

【CF 600E】Lomsat gelral(树上启发式合并, dsu on tree, 静态链分治,模板题)相关推荐

  1. CodeForces - 600E Lomsat gelral(树上启发式合并)

    题目链接:点击查看 题目大意:给出一棵树,每个节点都有一个编号代表一种颜色,现在对于每个子树求出现最多的颜色的编号之和 题目分析:因为n给到了1e5,看完这个题第一反应就是暴力n*n,但显然是会超时的 ...

  2. Codeforces 600E Lomsat gelral 树上启发式合并,线段树合并.

    文章目录 题意 题解 update:洛谷上已经可交此题. 题意 给一棵1为根的树,每个点有个颜色,求每一个点的子树里出现最多的颜色的和. 题解 我们用两组nnn个mapcnt和summap\ cnt和 ...

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

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

  4. [CF600] E. Lomsat gelral ( 经典树上启发式合并 dus on tree )

    题目链接:E. Lomsat gelral 题解 经典树上启发式合并的题目,按照正常暴力求时间复杂度为O(n2){O(n^2)}O(n2),很明显是有问题的.那么树上启发式合并是如何做的呢. 先说一些 ...

  5. 树上启发式合并问题 ---- D. Tree and Queries[树上启发式合并+树状数组]

    题目链接 题目大意: 就是给你一棵树,树上每个节点都有一个颜色,在你mmm次询问每次询问给你一个节点uuu和一个数字kkk,问你在uuu这颗子树里面又少种颜色的结点个数是大于kkk; 解题思路: 看到 ...

  6. 树上启发式合并问题 ---- D. Tree Requests [状态压缩+树上启发式合并]

    题目链接 题目大意: 就是给你一颗树,树上每个点都有一个小写字母,现在给你m∈[1,5e5]m\in [1,5e5]m∈[1,5e5]次询问,每次询问给你一个u,和deep,问你在u这课子树中,距离1 ...

  7. [dsu on tree]树上启发式合并总结(算法思想及模板附例题练习)

    文章目录 前言 树上启发式合并 引入 算法思想 时间复杂度 模板 练习 例题:CF600E Lomsat gelral solution code CF208E Blood Cousins solut ...

  8. 模板:树上启发式合并(dsu on tree)

    文章目录 解析 step1:树剖 step2:求出轻儿子的答案(不继承) step3:求出重儿子的答案(继承) step4:加入自己的答案.合并轻儿子的答案并记录答案 step5:清空 复杂度分析 代 ...

  9. 树上启发式合并(dsu on tree)

    dsu on tree dsu \text{dsu} dsu一般指 disjoint set union \text{disjoint set union} disjoint set union,即并 ...

最新文章

  1. 阅读Book: MultiObjective using Evolutionary Algorithms (1) --prologue 单目标和多目标的不同
  2. LESS 的 operation 是 特性
  3. 安装 Dubbo 管 理 控 制(二)
  4. 《ActionScript 3.0基础教程》——1.4 对象参数
  5. python3.8什么时候出来,【新版本来临!Python 官网宣布,正式发布Python3.8.0!】- 环球网校...
  6. [BJDCTF 2nd]8086(异或脚本解题)
  7. WPF使用Animation仿WeChat(微信)播放语音消息
  8. matlab 16位灰度值转8位,在matlab中如何将灰度值为24位的转化为8?
  9. jeecg-easypoi-2.0.3版本发布
  10. Eclipse导入类库【Java】
  11. CSDN-markdown编辑器的使用方法
  12. 微课|中学生可以这样学Python(5.5.3节):字符串格式化2
  13. 灰色模型 java代码_灰色模型的简单Java实现
  14. html中label宽度设置、非替换元素和替换元素
  15. matlab7.0的序列号
  16. springboot+vue网络课程教学网站系统java源码介绍
  17. Multisim14.0的安装步骤
  18. html编写在线打字通,HTML5代码打字练习、HTML5案例 - 03
  19. 元素周期表排列的规律_元素周期表中的几个规律
  20. 缥缈峰--JVM系列之内存区域

热门文章

  1. 操作系统的 (program)loader(程序加载器)
  2. Identity of indiscernibles(不可分与同一性)
  3. 中英文对照 —— 生物学基本概念
  4. 战争论 —— 蓝田之战
  5. 置换矩阵(permutation matrix)
  6. java 控制台输出到gui_java – 如何将类似窗口的“控制台”添加到GUI?
  7. threadlocal使用场景_ThreadLocal有没有内存泄漏?源码给你安排得明明白白
  8. 自学python编程笔记本推荐-这件神器,每个 Python入门学习者都值得一试
  9. python做excel自动化-用python进行办公自动化都需要学习什么知识呢?
  10. python画散点图-python画时间序列散点图