dsu on tree ——附带buff的暴力解法
这篇博客只是简单叙述思想(因为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的暴力解法的更多相关文章
- DSU On Tree——Codeforces 600E(E. Lomsat gelral)
有这么一类问题,要求统计一棵树上与子树相关的某些信息,比如:在一棵所有节点被染色的树上,统计每棵子树上出现次数最多的颜色编号之和. 很自然的可以想到用DFS序+主席树去求解,但是编码复杂度很高: 然后 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- dsu on tree入门
先瞎扯几句 说起来我跟这个算法好像还有很深的渊源呢qwq.当时在学业水平考试的考场上,题目都做完了不会做,于是开始xjb出题.突然我想到这么一个题 看起来好像很可做的样子,然而直到考试完我都只想出来一 ...
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- [学习笔记]Dsu On Tree
[dsu on tree][学习笔记] - Candy? - 博客园 题单: 也称:树上启发式合并 可以解决绝大部分不带修改的离线询问的子树查询问题 流程: 1.重链剖分找重儿子 2.sol:全局用桶 ...
- Codeforces.600E.Lomsat gelral(dsu on tree)
题目链接 dsu on tree详见这. \(Description\) 给定一棵树.求以每个点为根的子树中,出现次数最多的颜色的和. \(Solution\) dsu on tree模板题. 用\( ...
- Codeforces 600E. Lomsat gelral(Dsu on tree学习)
题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...
- Dsu on Tree
这个属于一种技巧,可以解决类似于子树询问无修改可离线的问题,一些点分治的问题也可以用Dsu on Tree解决,并且常数较小,代码复杂度低,很具有可写性. 整体上的意思就是继承重儿子的信息,暴力修改轻 ...
- Codeforces 600E Lomsat gelral(dsu on tree)
dsu on tree板子题.这个trick保证均摊O(nlogn)的复杂度,要求资瓷O(1)将一个元素插入集合,清空集合时每个元素O(1)删除.(当然log的话就变成log^2了) 具体的,每次先遍 ...
随机推荐
- springboot源码解析-管中窥豹系列之排序(五)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- 【C++】《C++ Primer 》第八章
第八章 IO库 一.IO类 1. 标准库定义的IO类型 头文件 作用 类型 iostream 从标准流中读写数据 istream, wistream 从流读取数据 ostream, wostream ...
- Go中由WaitGroup引发对内存对齐思考
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 WaitGroup使用大家都会,但是其中是怎么实现的我们 ...
- Rabbitmq可靠消息投递,消息确认机制
前言 我们知道,消息从发送到签收的整个过程是 Producer-->Broker/Exchange-->Broker/Queue-->Consumer,因此如果只是要保证消息的可靠投 ...
- MyISAM与InnoDB两者之间区别与选择(转)
Mysql在V5.1之前默认存储引擎是MyISAM:在此之后默认存储引擎是InnoDB MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Acces ...
- 【SpringBoot】Spring Boot 集成SwaggerAPI
Spring Boot 集成SwaggerAPI 文章目录 Spring Boot 集成SwaggerAPI Swagger 添加依赖 配置类 config 控制类 controller 接口测试 页 ...
- LeetCode454. 四数相加 II
题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 分析 关键是如何想到用 ...
- Java基础复习3
循环的嵌套 public class demo8 { public static void main(String[] args) { /* 输出######## ...
- django url别名和反向解析 命名空间
url别名和反向解析 我们平时写的url名字都是死的,如果项目过大,需要项目中某个文件名改动一下,那么改动起来就不是一般的麻烦了,所以我们就在定义的时候给url起一个别名,以后不管哪个文件中运用都是用 ...
- uni-app开发经验分享二: uni-app生命周期记录
应用生命周期(仅可在App.vue中监听) 页面生命周期(在页面中添加) 当页面中需要用到下拉刷新功能时,打开pages.json,在"globalStyle"里设置"e ...