【CF600E】Lomset gelral 题解(树上启发式合并)
题目大意:给出一颗含有$n$个结点的树,每个节点有一个颜色。求树中每个子树最多的颜色的编号和。
-------------------------
树上启发式合并(dsu on tree)。
我们先考虑暴力怎么做。遍历整颗树,暴力枚举子树然后用桶维护颜色个数。这样做是$O(n^2)$的,显然会T。我们需要一种更快的算法:树上启发式合并。
关于启发式算法的介绍,详见OI Wiki。本文只介绍树上启发式合并算法。本题的解法:
每处理完一颗子树,我们都要把桶清空一次,以免对它的兄弟造成影响。而这样做还要从它的祖先遍历一遍,浪费时间。
我们发现:遍历最后一颗子树时,桶是不用清空的。因为遍历完那颗子树后可以直接把答案加入$ans$中。那我们肯定选重儿子啊,省时省力。遍历轻儿子相对不费事。
看起来是不是没有快多少?实际上它是$O(n\log n)$的。下面是证明:
对于每个节点,它被计算的次数就是它到根节点路径的轻边个数。
而结点往上跳一次,子树大小至少为原来两倍,所以轻边个数最多是$\log n$。所以时间复杂度$O(n\log n)$。
证明过程跟树链剖分的有点像。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,color[],bucket[],ans[];
int size[],son[],sum,mx;
int head[],cnt;
struct node
{
int next,to;
}edge[];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
inline void dfs_son(int now,int fa)
{
size[now]=;
int mx=,p=;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (to==fa) continue;
dfs_son(to,now);
size[now]+=size[to];
if (size[to]>mx)
{
mx=size[to];
p=to;
}
}
if (p) son[p]=;
}
void getans(int x,int f,int p){
bucket[color[x]]++;
if(bucket[color[x]]>mx){
mx=bucket[color[x]];
sum=color[x];
}else if(bucket[color[x]]==mx)sum+=color[x];
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==f || y==p)continue;
getans(y,x,p);
}
}
inline void init(int now,int fa)
{
bucket[color[now]]--;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (to==fa) continue;
init(to,now);
}
}
inline void dfs(int now,int fa)
{
int p=;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (to==fa) continue;
if (!son[to])
{
dfs(to,now);
init(to,now);
sum=mx=;
}
else p=to;
}
if (p) dfs(p,now);
getans(now,fa,p);
ans[now]=sum;
}
signed main()
{
n=read();
for (int i=;i<=n;i++) color[i]=read();
for (int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs_son(,);
dfs(,);
for (int i=;i<=n;i++) printf("%lld ",ans[i]);
return ;
}
【CF600E】Lomset gelral 题解(树上启发式合并)的更多相关文章
- [Codeforces600E] Lomsat gelral(树上启发式合并)
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- Codeforces 600E Lomsat gelral (树上启发式合并)
题目链接 Lomsat gelral 占坑……等深入理解了再来补题解…… #include <bits/stdc++.h> using namespace std; #define rep ...
- 【学习笔记/题解】树上启发式合并/CF600E Lomsat gelral
题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. ...
- CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- dsu on tree (树上启发式合并) 详解
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...
随机推荐
- Scala 基础(三):Scala语言快速开发入门
1.Scala执行流程分析 2.Scala程序开发注意事项(重点) Scala源文件以 “.scala" 为扩展名. Scala程序的执行入口是main()函数. Scala语言严格区分大小 ...
- 数据可视化之powerBI基础(三)编辑交互,体验更灵活的PowerBI可视化
https://zhuanlan.zhihu.com/p/64412190 PowerBI可视化与传统图表的一大区别,就是可视化分析是动态的,通过页面上筛选.钻取.突出显示等交互功能,可以快速进行访问 ...
- 爬虫03 /代理、cookie处理、模拟登录、提升爬虫效率
爬虫03 /代理.cookie处理.模拟登录.提升爬虫效率 目录 爬虫03 /代理.cookie处理.模拟登录.提升爬虫效率 1. 代理 2. cookie处理 3. 模拟登录 4. 如何提升爬取数据 ...
- 数据可视化实例(七): 计数图(matplotlib,pandas)
https://datawhalechina.github.io/pms50/#/chapter5/chapter5 计数图 (Counts Plot) 避免点重叠问题的另一个选择是增加点的大小,这取 ...
- OSCP Learning Notes - Buffer Overflows(2)
Finding the Offset 1. Use the Metasploite pattern_create.rb tool to create 5900 characters. /usr/sha ...
- Ethical Hacking - Web Penetration Testing(4)
CODE EXECUTION VULNS Allows an attacker to execute OS commands. Windows or Linux commands. Can be us ...
- Ethical Hacking - GAINING ACCESS(13)
CLIENT SIDE ATTACKS Backdoor delivery method2 - backdooring exe downloads Backdoor any exe the targe ...
- Python Hacking Tools - Web Scraper
Preparation: Python Libray in the following programming: 1. Requests Document: https://2.python-requ ...
- 用前端姿势玩docker【四】基于docker快速构建webpack的开发与生产环境
目录 用前端姿势玩docker[一]Docker通俗理解常用功能汇总与操作埋坑 用前端姿势玩docker[二]dockerfile定制镜像初体验 用前端姿势玩docker[三]基于nvm的前端环境构建 ...
- NIO实践-HTTP交互实现暨简版Tomcat交互内核
今天就NIO实现简单的HTTP交互做一下笔记,进而来加深Tomcat源码印象. 一.关于HTTP 1.HTTP的两个显著特点,HTTP是一种可靠的超文本传输协议 第一.实际中,浏览器作为客户端,每次访 ...