CF1902F Trees and XOR Queries Again 题解
前言 本题是简单的、一眼的、普通的、显然的。 正文 0x00 分析题目 给定一颗带点权无根树,每次询问给定两个点 u,v 和参数 k,回答是否有一个 uleftarrow v 简单路径的点权子集其异或…
前言
本题是简单的、一眼的、普通的、显然的。
正文
0x00 分析题目
给定一颗带点权无根树,每次询问给定两个点 和参数 ,回答是否有一个 简单路径的点权子集其异或和是 。 时间限制为 秒。
可以肯定的是这个题需要线性基,以及线性基合并等知识,不会的推荐线性基学习笔记 | Menci's OI Blog。下文默认 同阶。
0x01 树上倍增
做法
首先考虑到一个显然的做法,树上倍增,对于每个 处理出 表示 到其 级祖先这条链的线性基,和普通树上倍增一样只不过合并两个 的信息时用线性基合并,则预处理时间复杂度 。
询问时, 不断向上倍增跳,直到其 的位置,这样一共需要合并 个线性基,单次询问时间复杂度 。
代码实现
实测使用一定的常数优化可以轻松通过:
- 线性基插入一个数 时从 位开始枚举,每次插入后重新取 寻找下一位。
- 树上倍增时从 开始倍增。
- 取 使用
31^__builtin_clz(x)计算最快。
AC CODE,最大点跑了 。
0x02 点分治做法
做法
观察发现树上倍增做法之所以慢是应为我们钦定了两个点在他们的 处相遇然后合并线性基,所以需要预处理和查询很多东西。但是对于这个这个题他是无根树,不需要一定在 处才能算。这启发我们使用点分治来处理树上询问。
具体的,对于每次点分治,处理跨越当前子树重心的所有询问。对于每个子树的点 处理出其到重心链上的线性基,这一部分不需要线性基合并,只需要直接继承他父亲的线性基然后加入 的点权即可。处理查询时合并以 到重心的线性基和 到重心的线性基即可。单次查询时间复杂度 ,点分治的时间复杂度 。
思考,点分治的好处是每次查询只需要合并两个线性基,并且预处理不需要合并线性基所以可以得到更优的时间复杂度。
代码实现
加上前面的优化甚至可以跑进一秒,AC CODE。
总结
本题利用了点分治对询问优秀的拆分方式解决了本题。
谢谢你,读到这里。
本文同步自洛谷专栏,保留原始正文与发布时间。在洛谷查看原文 ↗