Warning: session_start(): open(/tmp/sess_d155a42715d7451f48f9512e51863756, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:legal_string:jxm2001:树上启发式合并 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:树上启发式合并

树上启发式合并

算法简介

可离线处理子树相关信息统计的算法,时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。

算法思想

首先发现对每棵子树进行信息统计时,只需要合并所有儿子节点所在子树信息,最后加上该节点本身信息即可。

考虑信息合并的过程,类比并查集的启发式合并,发现把节点数少的子树信息合并到节点数多的子树将得到更优复杂度。

于是考虑保留重儿子子树的统计信息,然后暴力遍历轻儿子子树,合并结果。

具体实现为先 $\text{dfs}$ 处理轻儿子子树的询问,再删除轻儿子子树的统计信息(否则空间复杂度难以承受)。

然后处理重儿子子树的询问,但保留重儿子子树的统计信息,最后再次遍历轻儿子子树,然后把信息暴力合并。

关于时间复杂度,发现某个节点每被额外统计一次当且仅当他每有一个祖先节点为轻儿子。

由于每个节点到根节点最多有 $O(\log n)$ 条轻边,于是每个节点最多被统计 $O(\log n)$ 次,于是总时间复杂度为 $O(n\log n)$。

算法模板

2020-2021/teams/legal_string/jxm2001/树上启发式合并.1595733867.txt.gz · 最后更改: 2020/07/26 11:24 由 jxm2001