根号分治学习笔记

根号分治

根号分治其实一般是广义上的阈值分治,当范围不超过 \(B\) 时用一种方法,超过 \(B\) 时用另一种做法。

之所以叫根号分治主要是大部分的应用都是在和一定时,不超过 \(\sqrt{n}\) 的可以把所有 \(1\sim\sqrt{n}\) 的都处理,超过 \(\sqrt{n}\) 的最多只有 \(O(\sqrt{n})\) 个,也可以处理,并且 \(B\)\(\sqrt{n}\) 最优,于是通常叫根号分治。

P3645 [APIO2015] 雅加达的摩天楼

思路:直接根号分治即可。

设状态 \(f(i,j)\) 表示当前在点 \(i\),跳跃能力为 \(j\),那么当 \(j\le\sqrt{n}\) 时,只有 \(O(n\sqrt{n})\) 个状态,当 \(j>\sqrt{n}\) 时,最多只有 \(m\sqrt{n}\) 个状态。

P5309 [Ynoi2011] 初始化

题意:对等差数列下标加,区间和。

思路:一眼根分,但是小于根号的部分想了很久,感觉根周期有关,但是还是不会。

其实问题还是没往分块上想。可以直接根据周期来求,维护前缀后缀和就行了。

P5072 [Ynoi2015] 盼君勿忘

题意:求区间所有子序列分别去重后的和。

思路:首先,每一个数的贡献是好算的:\(i(2^{len}-2^{len-cnt_i})\),于是可以直接莫队维护出现次数,然后用光速幂,对于小于根号的出现次数可以直接维护,然后大于的就不会了。wsfw

然后才发现这样的数最多只有根号个,可以提前把这些数求出来,然后就没了。。。

P8427 [COCI2020] Paint

题意:有\(n\times m\)的网格,每个点有颜色,有\(Q\)次染色操作,每次会把包含\(x_i,y_i\)的极大同色连通块染成\(c_i\),求最终网格图。

思路:(码农题) 考虑根号分治,把大小小于\(\sqrt n\)的连通块称作小块,剩下的称作大块,对每个小块维护它与它相邻的大块集合,对每个大块,维护与它相邻的大块集合,并对其邻居维护一个哈希表,表示某种颜色的邻居集合。合并时采用启发式合并,复杂度\(O(nm\log(nm))\)

In a Trap

题意:有一颗以1为根的树,每个点上有一个点权ai,每次询问路径u到v上最大的 $ai \bigoplus dist(i,v) $,保证u为v的祖先

思路:神秘题。

不知道怎么就想到值域和树进行分块,就以 256 为块长,那么我们发现后 8 位和前面的是不影响的。我们设 \(dp[i][j]\) 表示从 \(i\) 点往上跳 \(j\) 步后从当前点及往上的 256 个点对 \(i\) 的答案,那么我们对于前面的位可以维护一个 Trie 树,对后 8 位可以维护一个桶。预处理后回答就很容易了。

You Are Given a Tree

题意:有一棵 \(n\) 个节点的树。

其中一个简单路径的集合被称为 \(k\) 合法当且仅当:

树的每个节点至多属于其中一条路径,且每条路径恰好包含 \(k\) 个点。

对于 \(k\in [1,n]\),求出 \(k\) 合法路径集合的最多路径数

思路:考虑对于一个 \(k\),我们可以类似求直径一样一遍树形 DP 求出答案,这样是 \(O(n^2)\) 的。

考虑怎么优化。首先,答案显然是单调不增的,而且 \(k>B\) 时答案不超过 \(\dfrac{n}{B}\),那么 \(<B\) 的部分可以直接做,\(>B\) 的部分就可以二分出每个答案对应的范围,复杂度为 \(O(n\sqrt{n\log n})\)

Frequency Problem (Hard Version)

题意:求最长的子区间使得其中有至少两个出现次数最多的元素。

思路:首先有结论:最终答案区间的众数一定有全局的众数。

证明很简单,如果全局众数不是区间的众数,那么可以把区间往外拓,一定存在两个众数且答案更优。

于是问题转成了求最长的区间满足有一个数出现次数和全局众数在这个区间的出现次数一样多。

考虑根号分治。如果另一个数的出现次数比 \(\sqrt{n}\) 大,可以 \(O(n)\) 扫一遍,然后用桶维护两个数出现次数的差,因为这样的数最多只有 \(O(\sqrt{n})\) 个,因此这一部分是 \(O(n\sqrt{n})\);否则枚举答案的出现次数 \(x\),每次 \(O(n)\) 求出满足条件的最长区间即可,这一步也是 \(O(\sqrt{n})\)

P8330 [ZJOI2022] 众数

题意:给一个序列,你可以把一个区间中的数加上任意数,要求最大化序列的众数出现次数。

思路:考虑这个操作的实质就是把序列分成 3 份,求两边的众数出现次数和区间内众数出现次数和的最大值。

这种跟众数相关的显然不好 \(\text{polylog}\),于是考虑用根号分治。

对于出现次数 \(>\sqrt{n}\) 的部分,可以先 \(O(n)\) 求出这个颜色对应前缀和,然后枚举另一个颜色,就可以在 \(O(\)另一个颜色的出现次数\()\) 的时间内计算答案。

然后就是小对小的贡献。这时可以直接扫描线,然后我们就需要快速维护区间众数。但是这时我们仅需处理出现次数不超过 \(\sqrt{n}\) 的,可以在修改时暴力更新,总复杂度不会超过 \(O(n\sqrt{n})\)

于是最终的复杂度就是 \(O(n\sqrt{n})\)

P8349 [SDOI/SXOI2022] 整数序列

题意:给定序列 \(a,b\),每次询问给定 \(x,y\),定义一个区间的权值是其中 \(a\) 值为 \(x\) 或者 \(y\)\(b\) 值和 ,求 \(x\) 的数量等于 \(y\) 的数量的区间的权值最大值。

思路:看上去又不太可以 \(\text{polylog}\)

可以对出现次数进行阈值分治。

  1. \(cnt_x,cnt_y\le B\)

可以直接 \(O(cnt_x+cnt_y)\) 暴力求答案。

  1. \(cnt_x,cnt_y>B\)

考虑这种询问的次数并不多,也可以暴力做,记忆化一下即可。

  1. \(cnt_x\le B,cnt_y>B\)

这种不好处理。考虑离线,对于 \(y\) 处理出所有 \(x\) 的答案。这时有一个很好的性质:对于一个 \(x\)\(y\) 中只有 \(O(B)\) 个数是有可能对答案产生贡献的,于是可以对于每一个 \(x\) 中的数 \(a\),可以找到前后第一个 \(y\),记作 \((pre_a,suf_a)\),然后可以和相邻的二元组合并,可能会在两边补上 \(y\)。直接做是 \(O(\dfrac{n^2}{B}+qB)\)

\(B\)\(\dfrac{n}{\sqrt{q}}\) 时可以取到最优,为 \(n\sqrt{q}\)

「JOISC 2017 Day 4」Dragon 2

题意:平面上有 \(n\) 个点和一个线段,每个点有颜色,现在有 Q 个操作,每个操作给出 \(x,y\),你需要求出如果从所有颜色为 \(x\) 的点引出所有经过颜色为 \(y\) 的点的射线,会经过线段多少次。

思路:计算几何+数据结构

因为所有颜色的点数和是 \(O(n)\) 的,这就有自然根号。

具体地,假设我们可以 \(O(C)\) 求出以一个点为起点,另一个颜色的点作为终点的射线经过线段的次数,或者一个点为中点,另一个颜色的点为起点的射线经过线段的次数,那么对于每次询问,我们可以在 \(O(min(|A|,|B|C))\) 的时间内计算答案。

如果 \(\min(|A|,|B|)<\sqrt{n}\),这样总共最多 \(O(Q\sqrt{n}C)\),如果 \(\min(|A|,|B|)>\sqrt{n}\),那么每种这样的颜色最多有 \(\sqrt{n}\) 次操作,总共最多 \(O(n\sqrt{n}C)\),于是总复杂度 \(O((n+Q)\sqrt{n}C)\)

然后考虑怎么求答案。先考虑第一种情况,能做贡献的点就在这个点和线段的端点连的射线之间的部分。

考虑如何计算。

我们把这个点和线段端点连起来,设这个三角形的底角分别是 \(\theta1,\theta2\)。我们把能作贡献的区域沿线段划分成两个部分,其中一个部分的点和线段连成的三角形的夹角 \(\lambda1,\lambda2\) 满足 \(\theta1\ge\lambda1,\theta2\ge\lambda2\),令一个部分满足 \(\lambda1\le\pi-\theta1,\lambda2\le\pi-\theta2\),如果把 \(\theta1,\theta2\) 看成 \(x,y\) ,那么可以转成二维数点问题,可以用主席树解决。

第二种情况和第一种类似,也可以转成二维数点。

复杂度 \(O((n+Q)\sqrt{n}\log n)\)

「JOISC 2018 Day 3」比太郎的聚会

题意:给定含有 \(n\) 个点 \(m\) 条单向边的有向图,每条边的边权值都为 \(1\)

给定 \(q\) 次询问,第 \(i\) 次询问给定一个点 \(T_i\),其中有 \(Y_i\) 个点无法前往 \(T_i\);假定剩下的点都会前往 \(T_i\),询问剩余的点中距离 \(T_i\) 最远距离是多少。

思路:考虑我们有两种做法,一种是每次询问 \(O(n)\) 求答案,一种是提前求出到每个点距离前 \(k\) 大的点,于是就可以根号分治,如果询问中删掉的点数小于 \(B\),就用提前预处理出的距离前 \(B\) 大的点来求,否则就暴力 \(O(n)\) 跑一遍,复杂度是 \(O(nB+QB+n\dfrac{Q}{B})=O(\sqrt{nq(n+q)})\)

P5071 [Ynoi2015] 此时此刻的光辉

题意:求区间乘积的约数个数。

思路:一开始只会 \(O(n\sqrt{n}\log a)\) 的做法,后来才知道可以阈值分治,对于小的质数用前缀和维护,大的质数用莫队维护,可以做到 \(O(n\sqrt{n})\)

posted @ 2024-02-13 11:38  Xttttr  阅读(30)  评论(0编辑  收藏  举报