从消息 x 只能往编号更小走:i→i-1,或(有引用时)i→r_i,每步 1 次操作。求到 y 的最少操作——本质是“只往左走”的最短路。
建图:每点连 i→i-1 和 i→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] 就是答案。
引用 r = [0,0,1,2,2,5]。弧线表示引用 i→r_i。绿色=终点 y,橙色=正在计算的 i,下方是 g 值。
Q1. 为什么这道题不会“绕圈”、可以直接 DP?
Q2. 计算 g[i] 时,引用 r_i 在什么情况下不能用?
Q3. 满分做法主要利用了哪个条件?
| i | r_i | g[i-1] | g[r_i](r_i≥2 才可用) | g[i] |
|---|---|---|---|---|
| 2 | — | — | — | 0(终点) |
| 3 | 1 | 0 | r=1<2 不可用 | 1 |
| 4 | 2 | 1 | g[2]=0 | 1 |
| 5 | 2 | 1 | g[2]=0 | 1 |
| 6 | 5 | g[5]=1 | g[5]=1 | 2 |
g[y]=0。r_i≥y 才可用,否则会跳过终点。