Description
跳房子的游戏规则如下:在地面上有一个起点,起点右侧有 $n$ 个格子,在同一直线上。每个格子内有一个整数,表示到达该格子能得到的分数。规则规定:玩家每次都必须跳到当前位置右侧的一个格子内,可以在任意时刻结束游戏,获得的分数为曾经到达过的格子中的数字之和。
小 $R$ 研发了一款弹跳机器人参加游戏。机器人有一个缺陷,它每次向右弹跳的距离只能为固定的 $d$ 。如果小 $R$ 花 $g$ 个金币改进他的机器人,机器人的灵活性就增加 $g$,但是每次弹跳的距离至少为 $1$。具体而言,当 $g<d$ 时,他的机器人每次可以选择向右弹跳的距离为 $d-g$ , $d-g+1$ , $d-g+2$ , $…$ , $d+g-2$ , $d+g-1$ , $d+g$;否则,他的机器人每次可以选择向右弹跳的距离为 $1$ , $2$ , $3$ , … , $d+g-2$ , $d+g-1$ , $d+g$。
小 $R$ 希望获得至少 $k$ 分,问他至少要花多少金币改造机器人。
数据范围:$1≤n≤500000 , 1≤d≤2000 , 1≤x_i , k≤10^9 , |s_i|<10^5$
做法1
二分答案。用 $dp$ 来判断当前答案是否可行。$f[i]$ 表示跳到第 $i$ 个格子的最大得分。如果 $f[0-n]$ 中有任意一个 $>=k$,当前答案可行。否则不可行。
另外注意,二分的右边界要取 $d$ 与第 $n$ 个格子到原点距离的最大值。
复杂度为 $O(n^2)$,可以得到 $50$ 分。
Code
1 |
|
单调队列优化
可以发现格子每次向后移动,答案区间也跟着向后滑动。区间的两端点单调递增。
对 $dp$ 验证过程加一个单调队列优化。$q$ 存的是编号,$next$ 是当前轮到哪一个点入队。$i$ 每加一次就使 $next$ 以及后面进入区间的都入队,使前面不再区间内的出队。如果队列非空:f[i] = f[q[head]] + s[i]
Code
1 |
|