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了) 具体的,每次先遍 ...
随机推荐
- Laya Ts 简易对象池
ts版本的简易对象池 ,目前主要支持3D的物体,也可以将其改成其他类型 要使用首先调用InitPool 方法 `/* 使用说明: 使用必须先调用 InitPool 方法将对象池初始化 然后 Deque ...
- 如何写一个自己的组件库,打成NPM包,并上传到NPM远程
1.首先使用vue create my_project 构建一个自己的Vue项目 2.vue.config.js和package.json配置如下,做了些修改 const path = require ...
- VmwareTools显示灰色无法安装
VMware不安装VMware Tools无法全屏,然后实机之间不能传输文件等. 安装Vmware Tools显示是灰色的,详细解决方案如下 打开虚拟机设置,CD/DVD 选择ISO映像文件 在Vmw ...
- 【计算机基础】常用的快捷键和DOS命令
常用的快捷键和DOS命令 DOS命令 使用Linux比较酷 cool
- Python eval 函数用途
Python eval 函数用途: eval 函数可将字符串转换成列表,元组和字典 实例如下: 可以把list,tuple,dict和string相互转化. ##################### ...
- merge join pg伪代码
Join { get initial outer and inner tuples INITIALIZE do forever { while (outer != inner) { SKIP_TEST ...
- 阿里云RDS物理备份恢复到本地
一:业务场景 验证阿里云备份文件可用性 二:恢复到本地过程中遇到的问题 1.修改密码报错 2.自定义函数不可用 三:恢复步骤 1.xtrabackup安装使用 请参考:https://www.cnbl ...
- Django orm中related_name/related_query_name区别
related_name/related_query_name区别 class Department(models.Model): title = models.CharField(verbose_n ...
- SQL性能优化汇总
SQL效率低下也是导致性能差的一个非常重要的原因,可以通过查看执行计划看SQL慢在哪里,一般情况,SQL效率低下原因主要有: 类别 子类 表达式或描述 原因 索引 未建索引 无 产生全表扫描 未利 ...
- ubuntu 14.04下安装 mysql-workbench
直接在命令行下运行下面命令: sudo apt-get install mysql-workbench 安装完,都可以在Dash中找到 "mysql" 就点击应用打开. 在data ...