根号分治及例题

根号分治的思想简介
根号分治,实际上是一种基于阈值
这里先讲一道板题:
CF1207F Remainder Problem IN Lv.13
这道题首先考虑暴力:
- 一种暴力是,加上就直接加,查询的时候就直接枚举所有下标
的位置,这种方法的修改复杂度为 ,查询时间复杂度为 。 - 另一种暴力是,枚举模数
,开一个二维数组 ,表示所有的下标 的位置的值之和。修改的时候就枚举所有的 ,就可以得到现在修改的下标 的结果,然后修改。查询直接查即可。修改时间复杂度为 ,查询时间复杂度为 。
现在我们得到了这两种暴力。而根号分治的用处这时就体现出来了。很明显,现在要糅合这两种暴力,因为第一种暴力的时间复杂度随
我们就定一个阈值
也就是,记录所有
然后在查询操作 2 x y
的时候,若
于是,这道题的时间复杂度就被平衡为了
1 |
|
HDU4858 项目管理
这道题似乎是我做的第一道 HDU。这道题很经典。
有两种暴力做法:
- 第一种,是直接暴力模拟,修改
,查询 。 - 第二种,是记录所有点的相邻项目的能量值的和,修改
,查询 。
于是开始平衡一下复杂度:我们定一个阈值
那么我们就记录,每一个点的所有的相邻“重点”编号(不会超过
查询的时候,如果
所以把
CF710D Two Arithmetic Progressions IN Lv.15
CF 2500。正解要使用 EX-GCD 状物。但是这里是根号分治区,所以我们要使用根号分治来艹过去。
首先,容易发现一个性质,假设某个数
所以我们可以看什么变量可以分出一个“阈值”出来。
一个暴力解法是,钦定
,然后枚举所有的在 并且在公差为 的等差数列里面的数字,看它在不在公差为 的等差数列里面即可。时间复杂度 。 另一种暴力解法是,因为
一个周期,所以我们只要找到 里面第一个在两个等差数列里的数就可以了。 那就可以首先把
设置为第二个等差数列里第一个比 和 都大的值。这是等价的,肯定要在 和 范围之内。然后搜索 里面有没有同时在两个等差数列里面存在的数。 - 若没有,则答案为
。 - 若有,则记录这个数的值
。根据循环周期和 可以算出来还有多少个重复的,也就是还有多少个周期在 里面。
时间复杂度
。 - 若没有,则答案为
我们发现,时间复杂度还是典型的
其他例题
P8250 交友问题 IN Lv.14
还是两种暴力方法:
- 记录所有点的相邻的点。然后搜索的时候就遍历
的邻点 ,看有没有 这条边。若没有,就算答案。否则不算。预处理时间复杂度 ,时间复杂度 。 - 将所有点的邻边都以
bitset
形式存每一个点里。相当于是一个第二维为bitset
的邻接矩阵bitset<N> nxt[N]
。然后查询的时候就查nxt[u] & (nxt[u] ^ nxt[v])
的popcount
即可。nxt[u]^nxt[v]
代表和都没有连边的点集。最后 and
一下的点集即可。预处理时间复杂度 ,查询时间复杂度 。
于是我们还是,设定一个阈值 bitset
的邻接矩阵的第一维就使用 vector
存储。
于是第一种的暴力的时间复杂度就变为了
P9809 [SHOI2006] 作业 IN Lv.13
还是,两种暴力:
- 直接模拟。修改复杂度
,查询复杂度 。虽然也是一种暴力,但是没有优化空间。重新想。 - 枚举
,记录所有数的 的最小值。查询时直接查即可。修改复杂度 ,查询复杂度 。 - 对第一种暴力进行一种优化:记录集合
(就是原题的集合),枚举 的倍数(从 开始枚举直到 ),记其为 。那么目前答案就是 中大于等于 的第一个数减去 ,即 *S.lower_bound(now) - now
。修改复杂度,查询复杂度 。
现在对第二种和第三种设定一个阈值
- Title: 根号分治及例题
- Author: 11490DX
- Created at : 2025-02-19 16:17:35
- Updated at : 2025-02-19 21:42:24
- Link: https://11490dx.net/2025/02/19/dac-sqrt/
- License: This work is licensed under CC BY-NC-SA 4.0.