从启发式合并到Dsu on Tree
从启发式合并到Dsu on Tree
传统启发式合并
[HNOI2009] 梦幻布丁
题目描述
例如,颜色分别为
输入格式
第一行是两个整数,分别表示布丁个数
第二行有
接下来
- 若
,则后有两个整数 ,表示将颜色 的布丁全部变成颜色 。 - 若
,则表示一次询问。
Sol:考虑初始答案就是看每一个数和自己前面的数是不是一样,算的时候多算n+1的目的是不需要特判处理边界,影响是答案固定需要减1。考虑合并过程,我们希望最后颜色是对的,所以我们保证x是小集合,向y这个大集合合并,但这样只会改变位置,不会改变位置对应的颜色。所以我们需要用modify函数维护位置的颜色,减去原颜色对答案的贡献,增加新颜色对答案的贡献。
启发式合并维护查询
【题解】金牌导航 启发式合并-连通性询问 - linyihdfj - 博客园 (cnblogs.com)
启发式合并,DSU on Tree - nannandbk - 博客园 (cnblogs.com)
启发式分治 https://hydro.ac/d/bzoj/p/4059
题意:一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子序列里至少存在一个数字只出现一次。现在给定一个整数序列,请你判断它是不是不无聊的。
Sol:考虑一个性质,如果一个数在当前序列只出现一次,那么包含这个数的区间都是合法的,再考虑分治解决左右区间不包含这个数的部分。利用双指针完成启发式分治,谁先找到就递归哪边。判定条件是利用map维护nxt和pre数组的位置。
debug:注意vector的resize不会清空,只会补充元素,所以要先clear
树上启发式合并
1.解决子树问题
- 只支持子树查询
- 不支持修改操作
给定一棵树,点带点权,问:最少多少次修改使得树上任意一条简单路径的点权异或和不为0。
Sol:我们只考虑在每条路径的lca处理,这也是树形dp常见的处理出发点。考虑钦定1为根,然后预处理树上异或前缀和d。考虑如果u和v之间存在非法路径,则 ==0 .考虑子树合并的过程中,我们给每个节点维护set,当我们合并子树的时候,我们采用启发式合并,保证合并次数的复杂度是 ,由于需要用set维护,每次合并的时候复杂度是 ,总时间复杂度是
考虑具体修改方案,我们只需要修改lca处的点权值改成很大,保证异或的时候高位的1消除不掉即可,所有经过lca的非法路径都将不复存在。
代码使用递归实现,常数较大,且本题使用的是set的启发式合并。后面代码将展示使用dfs序和重儿子优先的方式来减小常数。
Lomsat gelral题面:
-
有一棵
个结点的以 号结点为根的有根树。 -
每个结点都有一个颜色,颜色是以编号表示的,
号结点的颜色编号为 。 -
如果一种颜色在以
为根的子树内出现次数最多,称其在以 为根的子树中占主导地位。显然,同一子树中可能有多种颜色占主导地位。 -
你的任务是对于每一个
,求出以 为根的子树中,占主导地位的颜色的编号和。 -
Sol:考虑使用dsu on tree,每次先递归得到轻儿子答案,同时删除影响。再递归重儿子,保留贡献。二次递归轻儿子合并子树计算贡献。为什么不开O(n)个map去存储答案,从空间和时间上来说都非常差,所以我们考虑用一个数组原地修改,维护的答案及时清空。
递归版本:
dfs序优化常数版本:在合并轻儿子的子树过程中,直接利用dfs序for循环遍历所有节点进行答案更新,这样的方法和递归相比L虽然都是线性,但是for肯定快于递归的。
U41492 树上数颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
给一棵根为1的树,每次询问子树颜色种类数
Sol:合并子树的时候维护一个桶,每次有新颜色出现的时候答案加1。清除操作的时候答案清0,对应颜色的桶减1即可。
Tree and Queries - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 给定一棵
个节点的树,根节点为 。每个节点上有一个颜色 。 次操作。操作有一种:u k
:询问在以 为根的子树中,出现次数 的颜色有多少种。
, , 。
Sol:还是常规的可以直接dsu on tree.对于add操作,我们先维护颜色的桶,再维护出现次数的桶。删除操作的顺序值得注意,和add需要正好反过来。注意到询问的给出形式,我们需要将询问离线下来,对于同一个节点的U的不同k同时O(1)回答。对于离线问题我们需要保证输出答案的顺序,所以我们需要记录询问编号。
Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:一棵根为 的树,每条边上有一个字符(a
到 v
共 种)。一条简单路径被称为 Dokhtar-kosh,当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中最长的 Dokhtar-kosh 路径的长度。
说在前面:第一次见到这种判会回文串的套路是在dfs序配树状数组的时候。所谓的套路就是回文串的字母的出现次数最多只能有一个是奇数,其次就是由于我们只需要判断每个元素次数的奇偶性,这可以用异或做到,那再考虑如果出现的字母种类有限,我们可以状态压缩二进制数。
Sol:题解 CF741D 【Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths】 - 洛谷专栏 (luogu.com.cn)
题解 CF741D 【Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths】 - 洛谷专栏 (luogu.com.cn)
提供两篇比较好的代码和思路讲解。我的理解是对于子树问题,如果路径在内部,不经过当前的点,则递归下去去做。如果要求路径经过当前子树的根,则考虑路径两端一定在两颗子树内,进行合并子树过程。对于当前这个模型,要求长度最长,就是两端点距离最长,距离有lca经典公式得到。我们对于么每一个字符集状态维护对应得最大深度,那状态怎么转移保证终态合法。我们考虑只能异或全是偶数次或者一个奇数次得,这等价于异或0或者2的次幂。时间复杂度
debug:这个获得状态的过程是是从上而下的,需要递归前就得到当前节点的字符状态,懒的调,导致瞪眼一万年.对于叶子节点,答案应该是0,但这样算出来是负的,需要和0取max。调试完的endl没删,导致超时
to do list:Problem - F - Codeforces
启发式合并,DSU on Tree - nannandbk - 博客园 (cnblogs.com)
Tree Requests - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
2.利用dsu on tree解决树上路径问题
[P4149 IOI2011] Race - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
__EOF__

本文链接:https://www.cnblogs.com/mathiter/p/18199392.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话