GESP202603 八级真题 · 拔高 · 6/25 DP 思路拆解

P15804 消息查找

从消息 x 只能往编号更小走:i→i-1,或(有引用时)i→r_i,每步 1 次操作。求到 y 的最少操作——本质是“只往左走”的最短路。

一、先回答问题

结论

建图:每点连 i→i-1i→r_i(代价都 1)。 因为编号只减不增,是 DAG,可从终点 y 往上 DP: g[i]=1+min(g[i-1], r_i≥y ? g[r_i] : ∞)

满分钥匙

有引用的消息至多 1000 条。 最少操作 = (x-y) − 最大可省步数,跳一次 i→r_i 省 (i-r_i-1) 步; 满分在这 ≤1000 个关键点上做离线链式 DP。

二、核心观察

两种走法取较小

站在消息 i 想去更小的 y,只有两种下一步: 退到 i-1(稳);或顺着引用跳到 r_i(若 r_i≥y,否则会越过终点不可用)。

从 y 开始往上递推,每个 i 都取这两条里更省的一条,g[x] 就是答案。

三、互动演示:查询 x=6 → y=2

引用 r = [0,0,1,2,2,5]。弧线表示引用 i→r_i。绿色=终点 y,橙色=正在计算的 i,下方是 g 值。

终点 y=2(g=0) 正在算的 i 已算出 g

四、自己选答案

Q1. 为什么这道题不会“绕圈”、可以直接 DP?

Q2. 计算 g[i] 时,引用 r_i 在什么情况下不能用?

Q3. 满分做法主要利用了哪个条件?

五、手推结果(x=6, y=2 ⇒ 2)

ir_ig[i-1]g[r_i](r_i≥2 才可用)g[i]
20(终点)
310r=1<2 不可用1
421g[2]=01
521g[2]=01
65g[5]=1g[5]=12

六、C++14 参考代码(模型演示 / 部分分)

逐询问 DP,单次 O(x-y)
① 从终点 y 往上递推,g[y]=0
② 引用必须满足 r_i≥y 才可用,否则会跳过终点。
③ 此版稳过 40% 数据(n,q≤2000);满分需把跳跃点压到 ≤1000 个关键消息上离线处理。

七、接着练(同梯度)