1 条题解
-
0
自动搬运
来自洛谷,原作者为

TonyYin
AFOed.搬运于
2025-08-24 21:49:40,当前版本为作者最后更新于2021-04-07 20:40:52,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
数轴上有 个点,坐标分别为 在这些点上按照某些规则跳。
规则是:每次向距当前点第 小的点跳,如果有相同距离则向下标较小的跳;
求从每个点出发跳了 次后在哪里.
$1\leq k < n\leq 10^6, 1\leq m\leq 10^{18}, 1\leq p_i\leq 10^{18}$.
首先,注意到 是固定的,所以可以先预处理,对于每个点 ,跳一次之后的位置.
这部分使用单调队列处理。
我们知道,对于每个点,距离其前 小的点分布在其两侧,可以用一段完整区间覆盖。
所以我们想到,当单调队列枚举到 时,单调队列中维护的区间,就是覆盖距离 前 小的点的区间。这样找到区间内距离最大的点就是我们要求的 ,下面考虑考虑如何维护。
对于区间 中的一个点 ,距离他最远的点一定是 和 这两个点中的一个。如果 到 的距离小于了 到 的距离,说明区间应当向右滑动,如下图, 的例子:

绿色区间是距离点 前 小的点,考虑距离点 前 小的点。
,所以区间要右移一个单位,变成:

又因为 ,所以区间要再右移一个单位,变成:

至此,我们能够求出每个点,距离其第 小的点的下标。
head = 1, tail = k + 1; for(int i = 1; i <= n; i++) { while(tail + 1 <= n && x[tail + 1] - x[i] < x[i] - x[head]) head++, tail++; if(x[tail] - x[i] > x[i] - x[head]) nxt[i] = tail; else nxt[i] = head; }题目要求跳 次之后的答案,我们使用类似快速幂的方法,倍增处理即可。
for(int i = 1; i <= n; i++) pos[i] = i; while(m) { if(m & 1) { for(int i = 1; i <= n; i++) pos[i] = next[pos[i]]; } m >>= 1; for(int i = 1; i <= n; i++) next2[i] = next[i]; for(int i = 1; i <= n; i++) next[i] = next2[next2[i]]; }代码
最终代码在上面两部分的基础上加上 即可。
- 1
信息
- ID
- 2585
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者