1 条题解

  • 0
    @ 2026-5-16 15:03:57

    好的,我们基于之前的逻辑和代码,给出这道的详细题解


    题目重述

    我们有一条无限长的带子(坐标从 11101510^{15},两端之外视为离开),上面有 nn 个交通灯,位置 p1<p2<<pnp_1 < p_2 < \dots < p_n

    每个灯 ii 有延迟 did_i0di<k0 \le d_i < k)。
    灯在全局时间 tt 显示红灯当且仅当
    [ t \bmod k = d_i ] 否则显示绿灯。

    你在 t=0t = 0 时刻位于某个起始位置 aa,面向正方向(坐标增大的方向)。
    每个时刻的顺序操作:

    1. 如果当前位置是红灯 → 转身(方向取反)。
    2. 朝当前方向移动 11 格。

    问:能否在有限时间(1010010^{100} 秒内)离开带子(即到达 001015+110^{15}+1 以后)。


    关键难点

    • 位置范围极大(101510^{15}),不能直接模拟每一格。
    • 但灯的个数 n500n \le 500,所以关键事件只在灯的位置发生。
    • 灯的规律由时间模 kk 决定,k500k \le 500

    核心思想

    状态压缩:运动的“关键状态”是到达某个灯的时刻
    在灯与灯之间的大段距离中,不会发生任何状态变化(没有灯,所以方向不变,时间线性增长)。

    因此我们只需模拟“到达灯的时刻”。


    状态定义

    每个灯可以看作一个“反射点”。
    状态为: [ (i, \text{dir}) ] 表示我们位于灯 ii 的位置,正准备离开它朝方向 dir\text{dir}dir=+1\text{dir} = +1 表示向右,1-1 表示向左)。

    初始状态不是“位于灯上”,而是在某个起始位置 aa,方向 +1+1,但我们可先移动到第一个遇到的灯。


    转移规则

    假设我们处于状态 (i,dir)(i, \text{dir}),当前全局时间为 TT(到达灯 ii 的时刻)。

    情况 1:dir=+1\text{dir} = +1(向右)

    下一个可能到达的灯是 i+1i+1(如果 i+1<ni+1 < n),否则是右边界(离开)。

    到达灯 i+1i+1 的时间: [ T' = T + (p_{i+1} - p_i) ]

    检查是否红灯: [ \text{red} = (T' \bmod k == d_{i+1}) ]

    • 如果是红灯 → 方向变为 1-1(向左),新状态 (i+1,1)(i+1, -1)
    • 如果是绿灯 → 方向保持 +1+1,继续向右。但此时已在灯 i+1i+1 上,且绿灯,所以不会反弹,下一盏是 i+2i+2
      因此等价于转移到 (i+1,+1)(i+1, +1),但注意到达 i+1i+1 时未反弹,所以时间就是 TT'

    边界情况i=n1i = n-1 即最右灯):

    • 如果向右无灯,则到达右边界的时间 T=T+(1015pi)T' = T + (10^{15} - p_i),一定会离开 → YES

    情况 2:dir=1\text{dir} = -1(向左)

    类似,到达 i1i-1 的时间: [ T' = T + (p_i - p_{i-1}) ] 检查 (Tmodk==di1)(T' \bmod k == d_{i-1})

    • 红灯 → 方向变为 +1+1,新状态 (i1,+1)(i-1, +1)
    • 绿灯 → 方向保持 1-1,继续向左,新状态 (i1,1)(i-1, -1)

    边界:若 i=0i=0(最左灯),向左无灯,到达左边界时间 T=T+piT' = T + p_i,一定离开 → YES


    算法流程

    对于每个查询 aa

    1. 找到 aa 右边的第一个灯(可能没有)。

      • 如果没有 → 直接离开 → YES
      • 如果有,计算到达它的时间 T0=pfirstaT_0 = p_{\text{first}} - a
    2. 从该灯开始模拟状态转移,用 visited[i][dir] 记录是否访问过。

    3. 如果遇到边界 → YES

    4. 如果遇到重复状态(即已访问的 (i,dir)(i, \text{dir}))且不是边界 → NO(进入死循环)。


    复杂度分析

    • 状态数:2n2n
    • 转移时间 O(1)O(1)
    • 每个查询最多经过 2n2n 步就重复或离开。
    • 总复杂度 O(qn)O(q \cdot n),因 nn 总和与 qq 总和 500\le 500,完全可接受。

    示例推演(题目第一个样例)

    n=2,k=2,p=[1,4],d=[1,0],a=1n=2, k=2, p=[1,4], d=[1,0], a=1

    起始在 a=1a=1,即灯 0 的位置,t=0t=0

    灯 0 在 t=0t=0 时:0mod2=0d0=10 \bmod 2 = 0 \neq d_0=1 → 绿灯,方向不变 +1+1

    到达灯 1(p=4p=4),时间 t=41=3t=4-1=33mod2=1d1=03 \bmod 2 = 1 \neq d_1=0 → 绿灯,方向 +1+1,继续向右无灯 → 离开 → YES


    代码对应

    之前给出的 C++ 代码实现了这个模拟,核心就是跳过大区间、只在灯处判断红绿、检测重复状态。


    总结

    • 通过仅考虑灯的位置作为关键点,避免了大范围模拟。
    • 利用 kk 小的特点,用kk 判断红绿灯
    • 访问标记检测无限循环。
    • 边界处理 = 离开条件。

    这就将原来的连续大尺度问题转化为有限状态机的可达性问题

    • 1

    信息

    ID
    7107
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者