这篇博客只是简单叙述思想(因为ML太弱了),具体例题请转其他博客.


dsu on tree,许多OI将其归于启发式合并,当然如果你能理解更好,这只是一个理解方式罢了.

思想简述

  顾名思义,这个算法是处理树上问题,将子树分开求解,如果暴力了话是枚举每个子树,然后dfs;

  这里将每次dfs完的清空操作重新定义,并且规定dfs顺序,以来优化成log解法.

  这里我们引入一个 例题

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

  仔细读题我们可以先想到暴力解法,分别从一个点进行dfs,肯定会爆;

  那么我们思考一下,一颗子树上的点dfs结果是否可以被该子树根节点利用?

  当然可以,但是我们只能保留一个点的结果,所以我们就面临一个选择,留哪一个?

  我们想到树剖,那么我们保留重儿子就可以较好的保留信息,时间复杂度也会大幅降低.

操作步骤

  1.dfs1找到重儿子和轻儿子;

  2.dfs2递归处理每一个点,先扫描轻儿子,再扫描重儿子.

  3.设计calc函数,用来处理轻重儿子,可以将add和del分开写,也可以合在一起;

代码实现

  

#include<bits/stdc++.h>
#define maxn 100007
#define ll long long
using namespace std;
int n,head[maxn],a[maxn],sz[maxn],son[maxn],cent;
int fa[maxn],vis[maxn];
ll col,max_part,num[maxn],ans[maxn];
struct node{
int next,to;
}edge[maxn<<2]; template<typename type_of_scan>
inline void scan(type_of_scan &x){
type_of_scan f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
template<typename type_of_print>
inline void print(type_of_print x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
} inline void add(int u,int v){
edge[++cent]=(node){head[u],v};head[u]=cent;
edge[++cent]=(node){head[v],u};head[v]=cent;
} void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==fa[x]) continue;
fa[y]=x;dfs1(y);sz[x]+=sz[y];
if(sz[son[x]]<sz[y]) son[x]=y;
}
} void calc(int x,int p){
num[a[x]]+=p;
if(p>0&&num[a[x]]==max_part) col+=a[x];
if(p>0&&num[a[x]]>max_part) col=a[x],max_part=num[a[x]];
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==fa[x]||vis[y]) continue;
calc(y,p);
}
} void dfs2(int x,int id){
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,0);
}
if(son[x]) dfs2(son[x],1),vis[son[x]]=1;
calc(x,1);ans[x]=col;
if(son[x]) vis[son[x]]=0;
if(!id) calc(x,-1),max_part=col=0;
} int main(){
scan(n);
for(int i=1;i<=n;i++) scan(a[i]);
for(int i=1,u,v;i<=n-1;i++)
scan(u),scan(v),add(u,v);
dfs1(1),dfs2(1,1);
for(int i=1;i<=n;i++) print(ans[i]),putchar(' ');
}

dsu on tree ——附带buff的暴力解法的更多相关文章

  1. DSU On Tree——Codeforces 600E(E. Lomsat gelral)

    有这么一类问题,要求统计一棵树上与子树相关的某些信息,比如:在一棵所有节点被染色的树上,统计每棵子树上出现次数最多的颜色编号之和. 很自然的可以想到用DFS序+主席树去求解,但是编码复杂度很高: 然后 ...

  2. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  3. dsu on tree入门

    先瞎扯几句 说起来我跟这个算法好像还有很深的渊源呢qwq.当时在学业水平考试的考场上,题目都做完了不会做,于是开始xjb出题.突然我想到这么一个题 看起来好像很可做的样子,然而直到考试完我都只想出来一 ...

  4. BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)

    BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...

  5. [学习笔记]Dsu On Tree

    [dsu on tree][学习笔记] - Candy? - 博客园 题单: 也称:树上启发式合并 可以解决绝大部分不带修改的离线询问的子树查询问题 流程: 1.重链剖分找重儿子 2.sol:全局用桶 ...

  6. Codeforces.600E.Lomsat gelral(dsu on tree)

    题目链接 dsu on tree详见这. \(Description\) 给定一棵树.求以每个点为根的子树中,出现次数最多的颜色的和. \(Solution\) dsu on tree模板题. 用\( ...

  7. Codeforces 600E. Lomsat gelral(Dsu on tree学习)

    题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...

  8. Dsu on Tree

    这个属于一种技巧,可以解决类似于子树询问无修改可离线的问题,一些点分治的问题也可以用Dsu on Tree解决,并且常数较小,代码复杂度低,很具有可写性. 整体上的意思就是继承重儿子的信息,暴力修改轻 ...

  9. Codeforces 600E Lomsat gelral(dsu on tree)

    dsu on tree板子题.这个trick保证均摊O(nlogn)的复杂度,要求资瓷O(1)将一个元素插入集合,清空集合时每个元素O(1)删除.(当然log的话就变成log^2了) 具体的,每次先遍 ...

随机推荐

  1. LeetCode-151-中等-翻转字符串里面的单词

    问题描述 给定一个字符串,逐个翻转字符串中的每个单词. 说明: 无空格字符构成一个 单词 . 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括. 如果两个单词间有多余的空格,将反转 ...

  2. MySQL中的全局锁和表级锁

    全局锁和表锁 数据库锁设计的初衷是解决并发出现的一些问题.当出现并发访问的时候,数据库需要合理的控制资源的访问规则.而锁就是访问规则的重要数据结构. 根据锁的范围,分为全局锁.表级锁和行级锁三类. 全 ...

  3. 7.prometheus之查询API

    一.格式概述 二.表达式查询 2.1 Instant queries(即时查询) 2.2 范围查询 三.查询元数据 3.1 通过标签匹配器找到度量指标列表 3.2 获取标签名 3.3 查询标签值 四. ...

  4. GitHub README.md文本编写指南

    标题 在文字前写#,注意文字与#之间有一个空格 # 一级标题## 二级标题### 三级标题 以此类推或者用连续的减号或等号写在文字之下: 标题- 粗体斜体 **这个是粗体*这个是斜体****这个是粗体 ...

  5. 2019 Java开发利器Intellij IDEA安装、配置和使用

    进入Intellij IDEA的官网,选择电脑对应的合适版本进行下载,这儿我选择的是Intellij IDEA的社区版,安装旗舰版可去网上找相应的教程. Intellij IDEA的官网:https: ...

  6. HTML5表格详细教程

    HTML5表格 文章目录 HTML5表格 5.1 定义表格 5.1.1 普通表格.列标题 5.1.2 表格标题 5.1.3 表格行分组.表格列分组 5.2 表格属性 5.2.1 单线表格.分离单元格 ...

  7. Ubuntu20.04安装Typora

    Ubuntu20.04安装Typora 安装方法 # optional, but recommended sudo apt-key adv --keyserver keyserver.ubuntu.c ...

  8. .NET Core部署到linux(CentOS)最全解决方案,入魔篇(使用Docker+Jenkins实现持续集成、自动化部署)

    通过前面三篇: .NET Core部署到linux(CentOS)最全解决方案,常规篇 .NET Core部署到linux(CentOS)最全解决方案,进阶篇(Supervisor+Nginx) .N ...

  9. 列出HBASE所有表的相关信息,如表名、创建时间等。

    import java.io.IOException; import java.util.Collection; import java.util.Iterator; import org.apach ...

  10. 在HDFS中将文件从源路径移动到目的路径。

    import java.text.SimpleDateFormat; import java.util.Scanner; import org.apache.hadoop.fs.FSDataInput ...