Description
题目链接:BZOJ 2002
某天,Lostmonkey 发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey 在地上沿着一条直线摆上 $n$ 个装置,每个装置设定初始弹力系数 $k_i$,当绵羊达到第 $i$ 个装置时,它会往后弹 $k_i$ 步,达到第 $i+k_i$ 个装置,若不存在第 $i+k_i$ 个装置,则绵羊被弹飞。绵羊想知道当它从第 $i$ 个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey 可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
数据范围:$1\le n\le 2\times 10^5$,$1\le m\le 10^5$
Solution
解法 1(LCT)
首先我们建立一个虚点 $n+1$,意味着绵羊到达这个点就被弹飞。
对于每个装置,如果 $i+k_i\le n$,那么我们连边 $(i,i+k_i)$,否则连边 $(i,n+1)$。
对于修改操作,显然我们需要断开原来的边 $(i,i+k_i)$ 或 $(i,n+1)$,连上新的边 $(i,i+k)$ 或 $(i,n+1)$。由于要动态连边和删边,我们可以很自然地想到 $\text{LCT}$。
接下来我们考虑询问操作。对于询问 $x$,我们要查询的就是 $x$ 到 $n+1$ 这条链上的边的数量。于是我们就可以用 $\text{LCT}$ 的 $\text{split}$ 操作,得到 $x$ 到 $n+1$ 这条链的 $\text{Splay}$。我们只要维护 $\text{Splay}$ 中的节点个数,那么答案就是 $size_{n+1}-1$ 了。
时间复杂度:$O(m\log n)$
解法 2(分块)
考虑 $\sqrt n$ 分块。我们维护每个点它在块内可以往后跳动的次数,记为 $cnt_i$;跳动后到达块内最远点的位置(如果直接跳出块,那么记录跳动一次到达的位置),记为 $pos_i$。
对于修改操作,我们对 $x$ 所在块的信息暴力重新计算,复杂度为 $O(\sqrt n)$。
对于查询操作,我们从 $x$ 往后暴力跳,因为每个块内经过的次数是 $O(1)$ 的,那么复杂度为 $O(\sqrt n)$。
时间复杂度:$O(m\sqrt n)$(由于常数问题,分块比 $\text{LCT}$ 跑的要快 QAQ)
Code
解法 1
1 |
|
解法 2
1 |
|