CF1798C
形式化题意:
给出长为 \(n\) 的两个序列 \(\{a\}\) 和 \(\{b\}\),定义序列 \(\{c\}\) 满足:\(c_i=d_ib_i\),其中 \(d_i\mid a_i\)。求 \(\{c\}\) 最少能被分成多少个连续段,使得每个连续段内的值相同。
首先对于一个 \(i\),如果 \(c_i\) 能和 \(c_{i-1}\) 分到同一个段里,那么一定优于它单独成段或者和 \(c_{i+1}\) 分到同一段里。因为在一个段里加一个数只会让这个段的限制更紧。
基于这个贪心有了一个思路:对于一个左端点 \(l\),找到它能形成的最长合法连续段的右端点 \(r\),然后令 \(ans\leftarrow ans+1,l\leftarrow r+1\) 继续直到 \(l>n\)。
现在问题来到对于一个 \(l\),如何快速求 \(r\)。
不妨对 \(\{c\}\) 的构造方式做一下转化:\(c_i=\dfrac{a_ib_i}{e_i}\),其中 \(e_i\mid a_i\)。由此可以发现,如果一个区间 \([l,r]\) 合法,则这个区间的 \(c\) 值一定是 \(\gcd\limits_{i=l}^ra_ib_i\) 的约数,并且显然取最大公约数是最优的,由此可以求出每个 \(i\) 对应的 \(e\)。同时不难发现 \(r\) 的出现满足可二分性,因此只要 ST 表求区间 \(\gcd\),二分答案即可。
时间复杂度分析:ST 表初始化是 \(O(n\log^2 n)\)。设 \(len=r-l+1\),由于 check 在检测到不合法后立即返回,所以 check 一次的复杂度是 \(O(len)\),二分一次就是 \(O(len\log n)\),又因为 \(\sum len=n\),所以二分答案总时间复杂度为 \(O(n\log n)\)。程序总复杂度为 \(O(n\log^2 n)\)。常数好像挺小的。

浙公网安备 33010602011771号