这篇博客只是简单叙述思想(因为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. 【剑指 Offer】03.1.不修改数组找出重复的数字

    找出数组中重复的数字. 在一个长度为 n + 1 的数组 nums 里的所有数字都在 1-n 的范围内.所以数组中至少有一个是重复的.请找出数组中任意一个重复的数字. 示例 1: 输入: [2, 3, ...

  2. 剑指offer 查找和排序的基本操作:查找排序算法大集合

    重点 查找算法着重掌握:顺序查找.二分查找.哈希表查找.二叉排序树查找. 排序算法着重掌握:冒泡排序.插入排序.归并排序.快速排序. 顺序查找 算法说明 顺序查找适合于存储结构为顺序存储或链接存储的线 ...

  3. CopyOnWriteArrayList设计思路与源码分析

    CopyOnWriteArrayList实现了List接口,RandomAccess,Cloneable,Serializable接口. CopyOnWriteArrayList特性 1.线程安全,在 ...

  4. .NET 云原生架构师训练营(模块二 基础巩固 敏捷开发)--学习笔记

    2.7.1 敏捷开发 敏捷介绍 敏捷的起源 敏捷软件开发宣言 敏捷开发十二原则 生命周期对比 敏捷开发的特点 敏捷的发展 敏捷的核心 敏捷的起源 2001年,17个老头子在一起一边滑雪,一边讨论工作, ...

  5. jenkins + Ansible Plugin + ansi-color 让结果显示颜色

    1 安装jenkins: 此处省略百余字......   2 安装jenkins的插件: Ansible Plugin AnsiColor Plugin    3 设置job 内容 让ansible ...

  6. Pandas数据分析练手题(十题)

    数据集下载地址:https://github.com/Rango-2017/Pandas_exercises --------------------------------------------- ...

  7. 【Oracle】下载11.2.0.4的地址

    https://updates.oracle.com/download/13390677.html 这个地址就是下载Oracle 11.2.0.4版本的地址,需要有metalink账号才可以下载

  8. 快速查询表中的NULL数据

    正常情况下,NULL值是不会放入B-TREE索引的,因此根据IS NULL查询的时候走的通常是全表扫描,如果记录比较少还好,记录比较多,查询会非常耗时 可以通过创建一个索引来解决 CREATE IND ...

  9. java 日期与时间操作

    我们先来了解一下基本的概念 日期 2020-11-21 2020-11-22 时间 15:36:43 2020-11-21 15:36:43 时区 北京时间 2020-11-21 15:36:43 东 ...

  10. js input相关事件(转载)

    1.onfocus  当input 获取到焦点时触发. 2.onblur  当input失去焦点时触发,注意:这个事件触发的前提是已经获取了焦点再失去焦点的时候才会触发该事件,用于判断标签为空.3.o ...