1 条题解

  • 0
    @ 2025-12-11 2:51:09

    一、题意理解

    1. 模型抽象

    • nn 个服务器排成链 12n1-2-\dots-n
    • 服务器 ii 有缓存时间 tit_i:从它收到补丁开始,会把补丁保留 tit_i 秒,之后删除。
    • ii(连接 iii+1i+1)有通信时间窗口 [li,ri][l_i, r_i],只能在此时段内传输数据(传输瞬间完成)。
    • 传输规则:如果 AA 有补丁(在缓存中)且 BB 没有,且 AABB 之间的边正在通信窗口中,则 AA 立即传给 BB
    • 我们可以选择初始服务器 jj 收到补丁的时间 TjT_j
    • 问:对于每个 jj,最小的 TjT_j 使得最终所有服务器都能安装补丁。如果不可能,输出 1-1

    关键:补丁传播是双向的,且依赖于缓存时间与通信窗口的交集。


    二、思路分析

    1. 传播约束

    考虑从 jj 向两边传播的情况。

    对于左侧传播(从 ii 传到 i1i-1):

    • i1i-1 的窗口是 [li1,ri1][l_{i-1}, r_{i-1}]
    • 补丁到达 ii 的时间是某个时刻 xx(从 jj 一路传过来所花的时间)。
    • 为了传到 i1i-1,需要 xxii 的缓存期内与 [li1,ri1][l_{i-1}, r_{i-1}] 有交集。
    • 即:存在 y[li1,ri1]y \in [l_{i-1}, r_{i-1}] 使得 yxy \geq xyx+tiy \leq x + t_i

    等价于:

    $$x \leq r_{i-1} \quad\text{且}\quad x \geq l_{i-1} - t_i $$

    同时 xx 本身必须在 [li1,ri1][l_{i-1}, r_{i-1}][x,x+ti][x, x+t_i] 的交集非空,这实际上就是上面两个条件。

    因此,对于固定的 xx(到达 ii 的时间),能向左传的条件是:

    li1tixri1l_{i-1} - t_i \leq x \leq r_{i-1}

    2. 动态传播区间

    fl[i]fl[i] 表示:补丁到达 ii 的时间 xx 的范围,使得从 ii 能向左传播到 11 号服务器(如果 ii 在左边则向右传播的定义类似)。

    我们从 1 到 n 递推 fl[i]fl[i]

    • fl[1]=[0,]fl[1] = [0, \infty] 表示 1 号服务器作为最左端,任何时间收到补丁都能“传到左边”(左边没服务器,自然成功)。
    • 对于 i>1i > 1
      • 已知 fl[i1]fl[i-1] 是补丁到达 i1i-1 的时间范围,使得能继续向左传到 1。
      • ii 传到 i1i-1 的条件是:到达 ii 的时间 xx 满足 li1tixri1l_{i-1} - t_i \leq x \leq r_{i-1}
      • 同时,从 ii 传到 i1i-1 后,i1i-1 收到补丁的时间就是 y=max(x,li1)y = \max(x, l_{i-1})(因为如果 x<li1x < l_{i-1},要等到窗口开启才能传)。
      • 这个 yy 必须在 fl[i1]fl[i-1] 内,才能保证 i1i-1 能继续向左传。
      • 因此 xx 要满足:
        1. li1tixri1l_{i-1} - t_i \leq x \leq r_{i-1}
        2. max(x,li1)fl[i1]\max(x, l_{i-1}) \in fl[i-1]

    这等价于:

    • 如果 fl[i1]fl[i-1][li1,ri1][l_{i-1}, r_{i-1}] 无交集,则不可能传到左边,fl[i]=[1,1]fl[i] = [-1,-1]
    • 否则,xx 的范围是 fl[i1]fl[i-1][li1ti,ri1][l_{i-1} - t_i, r_{i-1}] 的交集,并考虑 xxyy 的约束。

    3. 代码中的简化

    你的代码实际上做了简化:

    if (fl[i-1].l == -1 || fl[i-1].r == -1)
        fl[i] = fl[i-1];
    else if (l[i-1] > fl[i-1].r || r[i-1] < fl[i-1].l)
        fl[i] = {-1, -1};
    else if (fl[i-1].l <= l[i-1])
        fl[i].l = max(0, l[i-1] - t[i]);
    else
        fl[i].l = fl[i-1].l;
    fl[i].r = min(r[i-1], fl[i-1].r);
    

    解释

    • 第一行:如果 fl[i1]fl[i-1] 已经无效,直接继承无效状态。
    • 第二行:如果窗口 [li1,ri1][l_{i-1}, r_{i-1}]fl[i1]fl[i-1] 无交集,则 ii 无法传到左边(因为即使传到 i1i-1i1i-1 也不能继续传)。
    • 否则:
      • 右端点 fl[i].r=min(ri1,fl[i1].r)fl[i].r = \min(r_{i-1}, fl[i-1].r),因为 xx 不能超过 ri1r_{i-1}(否则无法传),且 y=max(x,li1)y=\max(x,l_{i-1}) 必须在 fl[i1]fl[i-1] 内,所以 xfl[i1].rx \leq fl[i-1].r
      • 左端点:
        • 如果 fl[i1].lli1fl[i-1].l \leq l_{i-1},意味着 i1i-1 的最早可行时间 \leq 窗口左端,那么为了传到 i1i-1xx 只需满足 xli1tix \geq l_{i-1} - t_i(还要非负)。
        • 否则(fl[i1].l>li1fl[i-1].l > l_{i-1}),那么 i1i-1 需要时间 fl[i1].l\geq fl[i-1].l,因此 xx 至少为 fl[i1].lfl[i-1].l(因为 y=max(x,li1)xy=\max(x,l_{i-1}) \geq x,且 yfl[i1].ly \geq fl[i-1].l,所以 xfl[i1].lx \geq fl[i-1].l)。

    实际上这里隐含了 y=max(x,li1)y=\max(x,l_{i-1}) 必须在 fl[i1]fl[i-1] 内,所以推导出 xx 的范围是 fl[i1]fl[i-1][li1ti,ri1][l_{i-1}-t_i, r_{i-1}] 的交集,并做了等价化简。


    4. 双向传播

    同理,我们计算 fr[i]fr[i]:从 ii 能向右传到 nn 的到达时间范围。

    初始化 fr[n]=[0,]fr[n] = [0, \infty]

    从右向左递推,逻辑对称。


    5. 合并答案

    对于服务器 ii

    • 补丁从 ii 开始,要向左右两边传播。
    • 初始时间 TT 就是补丁到达 ii 的时间。
    • 要能传到左边,需要 Tfl[i]T \in fl[i]
    • 要能传到右边,需要 Tfr[i]T \in fr[i]
    • 因此 TT 必须在 fl[i]fr[i]fl[i] \cap fr[i] 中。

    取最小的 TT 就是 max(fl[i].l,fr[i].l)\max(fl[i].l, fr[i].l)(如果交集非空)。

    如果交集为空,输出 1-1


    三、算法步骤总结

    1. 读入 n,t[1..n],l[1..n1],r[1..n1]n, t[1..n], l[1..n-1], r[1..n-1]
    2. 从左到右递推 fl[i]fl[i]
      • fl[1]=[0,]fl[1] = [0, \infty]
      • i=2..ni=2..n,根据 fl[i1]fl[i-1] 和边 i1i-1 的窗口 [li1,ri1][l_{i-1}, r_{i-1}]tit_i 计算 fl[i]fl[i]
    3. 从右到左递推 fr[i]fr[i]
      • fr[n]=[0,]fr[n] = [0, \infty]
      • i=n1..1i=n-1..1,根据 fr[i+1]fr[i+1] 和边 ii 的窗口 [li,ri][l_i, r_i]tit_i 计算 fr[i]fr[i]
    4. 对每个 ii
      • 如果 fl[i]fl[i]fr[i]fr[i] 无交集,输出 1-1
      • 否则输出 max(fl[i].l,fr[i].l)\max(fl[i].l, fr[i].l)

    四、复杂度

    • 两次线性递推:O(n)O(n)
    • 空间 O(n)O(n)

    五、正确性要点

    • 核心是独立处理左右传播,因为链式结构中,向左和向右传播是独立的,只依赖于相邻边和缓存时间。
    • 递推公式正确捕捉了“到达时间必须使得下一站能继续传播”的约束。
    • 最终合并时,初始时间必须同时满足左右传播条件。

    六、举例验证

    以样例 3 为例:

    n=3
    t = [1,2,4]
    边1: [7,10]
    边2: [3,5]
    

    计算 flfl:

    • fl[1]=[0,]fl[1] = [0, \infty]
    • i=2i=2: l1=7,r1=10l_1=7, r_1=10, t2=2t_2=2 fl[1]fl[1][7,10][7,10] 交集 [7,10][7,10]fl[1].l=07fl[1].l=0 \leq 7,所以 fl[2].l=max(0,72)=5fl[2].l = \max(0, 7-2)=5fl[2].r=min(10,)=10fl[2].r = \min(10, \infty)=10,得 [5,10][5,10]
    • i=3i=3: l2=3,r2=5l_2=3, r_2=5, t3=4t_3=4 fl[2]=[5,10]fl[2]=[5,10][3,5][3,5] 交集为 [5,5][5,5],非空,fl[2].l=5>3fl[2].l=5 > 3,所以 fl[3].l=fl[2].l=5fl[3].l = fl[2].l = 5fl[3].r=min(5,10)=5fl[3].r = \min(5,10)=5,得 [5,5][5,5]

    frfr:

    • fr[3]=[0,]fr[3]=[0,\infty]
    • i=2i=2: l2=3,r2=5l_2=3, r_2=5, t2=2t_2=2 fr[3]fr[3][3,5][3,5] 交集 [3,5][3,5]fr[3].l=03fr[3].l=0 \leq 3,所以 fr[2].l=max(0,32)=1fr[2].l = \max(0,3-2)=1fr[2].r=min(5,)=5fr[2].r = \min(5,\infty)=5,得 [1,5][1,5]
    • i=1i=1: l1=7,r1=10l_1=7, r_1=10, t1=1t_1=1 fr[2]=[1,5]fr[2]=[1,5][7,10][7,10] 无交集,所以 fr[1]=[1,1]fr[1]=[-1,-1]

    合并:

    • i=1i=1: fl[1]=[0,]fl[1]=[0,\infty], fr[1]=[1,1]fr[1]=[-1,-1],无交集,输出 1-1
    • i=2i=2: fl[2]=[5,10]fl[2]=[5,10], fr[2]=[1,5]fr[2]=[1,5],交集 [5,5][5,5],输出 55
    • i=3i=3: fl[3]=[5,5]fl[3]=[5,5], fr[3]=[0,]fr[3]=[0,\infty],交集 [5,5][5,5],输出 55

    与样例输出一致。


    这样就完成了题解。该算法的关键在于双向独立递推传播时间可行区间,最后取交集得到最早可行初始时间。

    • 1

    信息

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