区间GCD分块
区间GCD分块
HeJie引言
区间GCD分块就是将前/后缀的GCD数组按照数值分块。
其数学原理是,对于任意长度的数组
这里有两种方法,第一种是二分加st表的方法,时间复杂度为
正文
【题目描述】
给定一个长度为
的正整数数组 。现在有 次独立询问,每次询问给定一个整数 。对于每个询问,你需要回答:数组中有多少个连续子区间 ( ),满足该区间的 ? 【数据范围】
询问的
第一种做法
st表可以快速得到区间gcd。对于任意一个区间,由于区间中的前/后缀gcd值最多只有
对于例题,我们可以枚举所有的区间左边界,然后对前缀gcd进行分块,找到gcd值为
第二种做法
这种做法有点像第一种做法的逆向思维,它不是固定一个点不动,然后让其往一个方向蔓延来找区间,而是一个一个的将点加入进已经分好的块中。
具体来说,我们从左到右扫描数组,然后维护一个以这个点为起点,所造成的后缀gcd分块。
由于口述不太好理解,我用AI举了个例子,帮助理解具体的过程。
点击展开
请把视线聚焦在下面的“📦 块列表”上,看它们是怎么变化和融合的:
初始状态:数组 A = [12, 6, 18, 40]
⏱️ 第一步:扫描线来到位置 1(当前数字:12) 此时只有一个数字,自成一派。
- 📦 当前块列表:
[块A] 左边界:1 | 右边界:1 | GCD值: 12
⏱️ 第二步:扫描线来到位置 2(当前数字:6) 现在,我们要把新来的 6 滴加到前面的块里。
- 反应:旧的
[块A]里的 12 遇到 6,。 - 新兵:新位置 2 的数字自己形成一个值为 6 的区域。
- 💥 发生融合:因为前面的块变成了 6,新来的也是 6,连成一片了!
- 📦 当前块列表(更新后):
[块A] 左边界:1 | 右边界:2 | GCD值: 6
⏱️ 第三步:扫描线来到位置 3(当前数字:18) 把新来的 18 滴加到前面的块里。
- 反应:旧的
[块A]里的 6 遇到 18,。(没变) - 新兵:新位置 3 的数字自己形成一个值为 18 的区域。
- 观察:前面的值为 6,后面的值为 18。不一样,无法融合。
- 📦 当前块列表(更新后):
[块A] 左边界:1 | 右边界:2 | GCD值: 6[块B] 左边界:3 | 右边界:3 | GCD值: 18
⏱️ 第四步:扫描线来到位置 4(当前数字:40) 👈 最神奇的一步! 把新来的 40 滴加到前面所有的块里。
- 反应 1:旧的
[块A](值6) 遇到 40,。 - 反应 2:旧的
[块B](值18) 遇到 40,。 - 新兵:新位置 4 的数字自己形成一个值为 40 的区域。
- 💥 发生超级融合:你发现了吗?原本不一样的
[块A]和[块B],在遇到 40 之后,它们的 GCD 都变成了 2!既然数值一样,并且物理位置是挨着的(12 和 33),立刻吃掉边界,融合成一个大块! - 📦 当前块列表(最终更新):
[超级块A] 左边界:1 | 右边界:3 | GCD值: 2[块B] 左边界:4 | 右边界:4 | GCD值: 40
|

