学习总结:Dsu on tree 树上启发式合并
来源:互联网 发布:ftp传输数据的具体方式 编辑:程序博客网 时间:2024/05/21 20:12
(RT,这只是一篇小小的总结,以便将来的回顾,并不详细讲)
以前也学习过启发式合并,大概就是像树形dp一样在dfs上,将儿子的信息向父亲转移,容器是map,将儿子的信息边转移边更新答案,转移之后便将儿子的容器清空,防止空间超限。不过对于本人而言,虽然思路较为简便,但是因为有用到map的迭代器,所以这种写法写起来较为繁琐。
最近学了一种基于dfs序的一种的启发式合并,特点就是:暴力。
看似暴力。
算法的流程大概是这样:
1、dfs将一棵树建好,将节点的size、dfs序、重儿子、该dfs序对应的节点这些信息处理好(其他的信息具体问题具体分析)。
2、进入solve函数,先去解决非重儿子,然后将这些非重儿子的信息暴力清空。
3、接下来解决重儿子,这次不清空。
4、然后再将非重儿子的信息再暴力添加。
5、将该节点的信息添加进容器。
6、回答关于这个节点的问题。
7、返回。
注意:这里的添加是利用dfs序进行的。
流程还是有点繁琐,那就看代码吧。
void build(int p,int pre,int d){ sz[p]=1; dep[p]=d; l[p]=++dfn; f[dfn]=p; for(int i=0;i<e[p].size();i++){ int v=e[p][i]; build(v,p,d+1); sz[p]+=sz[v]; if(sz[v]>sz[son[p]])son[p]=v; } r[p]=dfn;}void del(int p){ for(int i=l[p];i<=r[p];i++)sum[dep[f[i]]]--;}void ins(int p){ for(int i=l[p];i<=r[p];i++)sum[dep[f[i]]]++;}void solve(int p){ int to=son[p]; for(int i=0;i<e[p].size();i++){ int nx=e[p][i]; if(nx!=to)solve(nx),del(nx); } if(to)solve(to); if(!p)return; for(int i=0;i<e[p].size();i++){ int nx=e[p][i]; if(nx!=to)ins(nx); } sum[dep[p]]++; for(int i=0,sz=ask[p].size();i<sz;i++)ans[ask[p][i].id]=sum[ask[p][i].k]-1;}
相信看到代码的时候就在想,这不是暴力吗?
这其实和普通的启发式合并的核心是一样的:普通的启发式合并的复杂度是O(nlogn),是因为每次合并是将小集合并到大集合,对于小集合来说,合并后,集合的size至少扩大到原来的2倍,那么合并的次数一定小于等于logn。然后看有n个点,所以所有点合并的次数就是nlogn。考虑在map合并自带的复杂度,以及清空内存的复杂度,这样近似暴力的启发式合并的复杂度也就近似O(nlogn)了。
同理,每一个重儿子合并的次数也是logn。
所以Dsu on tree的复杂度同样是近似O(nlogn)。
当然对于存信息的sum不一定是普通的数组,可能是map,可能是树状数组这类既支持插入又支持删除的容器,有适合的数据结构,而不是用数据结构去套题。
这种算法能够解决关于询问一棵树的子树的相关信息的问题。
当然,算法是好的,关键是在足够理解的基础上能够用起来!
- 学习总结:Dsu on tree 树上启发式合并
- [BZOJ2599][IOI2011]Race-树上启发式合并(dsu on tree)
- dsu on tree(树上启发式合并)简介(codeforces 600 E)
- 启发式合并/dsu on tree 姿势
- codeforces 600E. Lomsat gelral [dsu on tree(树上启发式合并)]
- dsu on the tree 学习笔记
- 树上启发式合并
- poj1741:Tree (树上点分治/treap+启发式合并)
- POJ1741 Tree (树上点分治/treap+启发式合并)
- [trick]dsu on tree
- dsu on tree
- [trick]dsu on tree
- Dsu on tree
- 【算法】树上启发式合并算法
- HDU6191Query on A Tree(字典树启发式合并)
- [hdu 6191 Query on A Tree] 字典树启发式合并
- cf570D. Tree Requests(dsu on tree)
- codeforces600E Lomsat gelral -- 树上启发式合并
- Hadoop NameNode的Federation
- 49. Group Anagrams(unsolved)
- Pandas 文本数据方法 pad( ) center( ) ljust() rjust() zfill()
- BZOJ4750 密码安全
- linux目录命令基础
- 学习总结:Dsu on tree 树上启发式合并
- 将C++对象嵌入到带有上下文属性的QML中
- Vim系列-选择多行
- 蓝桥杯:算法训练 Anagrams问题
- ajax的运用
- django查询mysql数据 从数据库提出并分页展示
- Linux下shell编程入门
- C++数据类型中的复合类型
- 38. Count and Say(unsolved)