Codeforces 1737G - Ela Takes Dancing Class(平衡树)

发布时间 2023-06-06 17:34:14作者: tzc_wk

数据结构好题。

先考虑如果 \(s_i\) 全是 \(1\) 怎么做。考虑一个非常特殊的状态:如果当前最靠左的舞蹈者跳一步就能跳到最靠右的舞蹈者的右边,那么这样的局面性质其实是非常完美的。因为容易归纳证明,这样的局面下,每一步最靠左的舞蹈者跳一步都能跳到最靠右的舞蹈者的右边,这样一来,如果维护出了初始局面下 \(n\) 个人坐标排序后的结果,那么就可以 \(O(1)\) 地算出 \(k\) 轮以后某个人的位置,进而求出答案。

考虑更一般的情况,如果第一步中第 \(1\) 个人恰好跳过了第 \(x\) 个人,那么我们就称当前前 \(x\) 个人形成了一个“完美局面”。那么这个过程显然是,随着时间线的推移,\(x\) 不断增加。由于 \(x\) 的变化是 \(O(n)\) 的,所以我们只要知道,如果当前前 \(x\) 个人形成了“完美局面”,至少需要多少轮后第一个人能够跳过第 \(x+1\) 个人即可。这一部分我们二分答案 \(mid\)。先假设前 \(mid\) 轮没有跳过第 \(x+1\) 个人,算一下 \(mid\) 轮后最后一个人的位置,如果超过第 \(x+1\) 个人当前的位置说明 \(mid\) 轮内 \(x\) 已经增加了,因为如果跳过了 \(x+1\) 那么 \(mid\) 轮后最后一个人的位置肯定比我们计算出的值大。使用平衡树维护即可。对于一个完美局面而言,进行 \(mid\) 轮后的结果对顺序的影响实际上是一个 cyclic shift,即将一段后缀与一段前缀 merge 起来,除此之外还需要实现前(后)缀加与查询第 \(k\) 小的值的位置。这是容易用平衡树维护的。

接下来考虑有 \(s_i=0\) 的情况,其实也比较好办,对于 \(s_i=0\) 的舞蹈者,先当他是可以移动的,然后计算下最早什么时候会出现“坐标最小的舞蹈者是不可移动”的情况,如果这段时间内 \(x\) 没有增加,就暴力跳到那一时刻然后将最小的元素从平衡树里删掉即可。

时间复杂度 \(n\log^2n\),代码看上去还挺难写的,先咕着。