一类做法基于变化次数的题目的总结
最近遇到不少这类题目啊,但自己像个【数据删除】一样完全没有总结经验,被花式吊打。所以痛定思痛,决定总结一下。
CF475D. CGCDSSQ
我们可以把询问离线下来,求区间 \(\gcd\) 等于 \(x\) 的等价于求区间 \(\gcd\) 不大于 \(x\) 的减去不大于 \(x-1\) 的。考虑固定左端点,每次暴力往右拓展,这是 \(O(n^2\log n)\) 的。
现在,我们要用到一个结论:当你拓展的时候,区间 \(\gcd\) 要么不变,要么至少缩小一半。所以你可以每次二分找到会使得 \(\gcd\) 变小的那个右端点,用 ST 表维护区间 \(\gcd\),时间似乎是 \(O(n\log n\log^2 A)\) 的,但常数极小:后面的 \(\log A\) 是求 \(\gcd\) 的复杂度,可以忽略不计;前面的二分也是跑不满 \(\log n\log A\) 的。
CF1834E. MEX of LCM
还是那个性质:当你拓展的时候,区间 \(\text{lcm}\) 要么不变,要么至少变大一倍。第 \(3\times 10^5\) 个质数是 4256233,故我们只需要不超过 4256234 的数。
我的写法很劣,不知道为什么过不了,所以下面是 emsger 的写法。假设当前枚举到 \(a_i\),考虑开一个双端队列维护以 \(i\) 为右端点的所有可能的 \(\text{lcm}\),同时每次把能得到的数丢进 map 里,最后求 mex 即可。优化就是如果这个双端队列是 \([i,i],[i-1,i]\ldots[1,i]\) 的顺序的话,那么这些 \(\text{lcm}\) 是不减的,且一定是倍数关系。如果当前已经超过答案上限/能被 \(a_i\) 整除,说明也不用看后面的了。这似乎在 \(a_i\) 很小时有巨大优化。
D 【0506 B组】简单的数据结构题
发现如果我们固定一个左端点 \(i\),因为区间变大 and 不增,且一旦变小至少会有一个 1 变为 0,那么这些区间的 and 至多有 \(\log A\) 种取值。可以从右往左枚举 \(i\),维护 \(pos_j\) 表示当前经过的所有 \(k\) 中,满足 \(a_k\) 第 \(j\) 位为 0 的最大的 \(k\)。这样我们就在 \(O(n\log A+n\log A\log\log A)\) 的时间内求出了每个 \(i\) 的 and 值的分割点(后面那个是排序 + 去重的时间)。
现在,我们把询问都离线下来,按左端点从大到小排序。从右往左枚举 \(i\),有一些分割点把 \(i\) 到 \(n\) 分成了若干段,以 \(i\) 为左端点,同一段内的若干个下标作为右端点,得到的 and 是相同的。这样,对于每个 \(i\),我们可以在 \(\log A\) 的时间内求出哪些区间的 and 是完全平方数(因为每段中间的数一定不会影响 and 的值)。
现在,我们把那些 and 为完全平方数的区间,以右端点为下标,丢到一颗线段树上维护。对于询问 \([ql,qr]\),我们只用查询线段树上 \([ql,qr]\) 区间的和即可。因为我们以右端点为下标,故会对答案造成贡献的区间 \([l,r]\) 满足 \(r\le qr\)。同时,枚举 \(i\) 的顺序也决定了 \(l\ge ql\),所以这样统计是不重不漏的。
A 【0630 B组】冤
你可以假定 \(\forall i\in[1,n],a_i\ge1\)。
唉,被诈骗了。
因为三角形需要满足两边之和大于第三边,显然最优选法是排序后取相邻三个。考虑最坏情况,即所有长度构成斐波那契数列。因为 \(a_i\le10^9\),故长度过大的区间一定合法,剩下的暴力判断即可。