1 条题解

  • 0
    @ 2026-9-3 10:39:17

    题解

    思路

    依次处理灯笼。令 dpidp_i 表示只决定前 ii 个灯笼的方向后,可以确认已经被照亮的最远位置。尚未被确认照亮的末尾若干灯笼暂时都朝右,它们可以在之后被某个朝左的灯笼照亮。

    记

    li=max⁡(1,i−pi),ri=min⁡(n,i+pi).l_i=\max(1,i-p_i),\qquad r_i=\min(n,i+p_i).

    处理第 ii 个灯笼时有两类转移。

    第一类令它朝右。如果此前已有 dpi−1≥idp_{i-1}\ge i,说明第 ii 个灯笼已经被照亮,它朝右后可以把最远照亮位置更新为 max⁡(dpi−1,ri)\max(dp_{i-1},r_i)。也可以暂时不确认它及其右侧贡献,保留 dpi=dpi−1dp_i=dp_{i-1},等待后面的朝左灯笼收束这一段。

    第二类令它朝左。设某个旧状态为 mm,并让第 m+1m+1 到第 i−1i-1 个灯笼全部朝右、第 ii 个灯笼朝左。只要 dpm≥li−1dp_m\ge l_i-1,第 ii 个灯笼就能接上此前已经覆盖的前缀,并照亮这一整段的左侧。新状态为

    dpi=max⁡(i−1,max⁡m<q<irq).dp_i=\max\left(i-1,\max_{m<q<i}r_q\right).

    在所有满足 dpm≥li−1dp_m\ge l_i-1 的状态中,最小的 mm 一定最优,因为它包含的朝右灯笼区间最大。记录每次转移的来源即可反向恢复方向字符串。

    直接枚举 mm 可以得到平方算法。满分算法需要维护两种查询:

    • 按 dpmdp_m 的值查询所有 dpm≥li−1dp_m\ge l_i-1 中最小的下标 mm;
    • 查询一段连续灯笼的 rqr_q 最大值。

    分别使用维护区间最小值和区间最大值的线段树,就能在对数时间完成一次转移。

    做法

    初始化 dp0=0dp_0=0。把每个已经得到的状态 ii 按照键 dpidp_i 插入第一棵线段树,叶子保存该键对应的最小状态下标;在后缀区间 [li−1,n][l_i-1,n] 查询最小值,即得到第二类转移所需的最小 mm。

    第二棵线段树预先存储所有 rir_i,用于查询 m+1m+1 到 i−1i-1 的最大右端点。然后依次比较朝左成段转移、已被照亮后朝右转移和暂缓确认转移,保留使 dpidp_i 最大的来源。

    若最终 dpn=ndp_n=n,则所有位置都能被照亮。根据来源数组从 nn 反向恢复:普通转移把当前灯笼设为 R;成段转移把末端设为 L,中间灯笼设为 R,再跳回旧状态。若 dpn≠ndp_n\ne n,则不存在合法方案。

    上述转移枚举了最后一个朝左灯笼收束未确认后缀的位置,因此不会漏掉任何合法方案;每个得到的状态也对应一份可恢复的合法前缀方案,所以算法同时具有充分性和必要性。

    复杂度

    设所有数据组的灯笼总数为 NN。时间复杂度为 O(Nlog⁡N)O(N\log N),空间复杂度为 O(N)O(N)。

    • 1

    信息

    ID
    1269
    时间
    2000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者