CodeForces 20251003 - ?
1. 2152F Triple Attack
超级倍增题
题意
若一个可重集任意三个元素的最大值与最小值之差大于给定常数 zzz,那么称其是安全的。现在给出一个递增的数列,若干次询问,每次问一个区间,求该区间的最长安全子序列的长度。
n,Q≤2.5⋅105,ai≤109n,Q\le2.5\cdot10^5,a_i\le10^9n,Q≤2.5⋅105,ai≤109
做法
如果限制是两个元素只差,那么容易想到用 lower_bound
和倍增求解。
现在是三个元素,贪心的做法是先去区间前两个元素,然后后面若一个元素加进来合法那么一定取,证明是容易的:若前两个元素不取,那么把取到的前两个元素换成区间前两个元素一定可行;若遇到一个合法的元素不直接取,那么取后面的元素一定会对后续限制更强。
所以我们仍然可以考虑用倍增,元素 aia_iai 的下一个元素表示下标在 i+1i+1i+1 之后(不含)的第一个合法元素,反复取下一个元素可以得到一条合法链。我们考虑从 l,l+1l, l+1l,l+1 开始的两条链,要么他们不相交,那么就得到答案,要么他们相交,发现相交的元素类似 LCA,具体来说:考虑在一个元素和该元素的下一个元素之间建边,lca(l,l+1)lca(l, l+1)lca(l,l+1) 即为最早相交处,那么只要再取 lca,lca+1lca, lca+1lca,lca+1 重复上述步骤即可,这样多次从 lll 跳跃到 lca(l,l+1)lca(l, l+1)lca(l,l+1) 的过程也可以倍增,倍增到最后如果 lca>rlca>rlca>r 那么就把最后一段按照不相交时的“下一个元素”的倍增求。
简单来说是一个先大步倍增,后小步倍增的感觉,复杂度 O((n+Q)logn)O((n+Q)\log n)O((n+Q)logn)。
code
总结
如果选取元素的过程是线性的贪心做法,那么可以考虑倍增。考虑倍增到相同位置是可以考虑转化为树上 LCA。