1 条题解

  • 0
    @ 2026-5-16 17:01:41

    问题重述

    我们有一个初始数组 aa,经过 qq 次操作后得到数组 bb。第 ii 次操作是:

    czi:=min(cxi,cyi)c_{z_i} := \min(c_{x_i}, c_{y_i})

    已知最终数组 bb 和所有操作 (xi,yi,zi)(x_i, y_i, z_i),要求构造一个可能的初始数组 aa,或判断无解。


    核心思想:逆向推导约束

    我们不知道初始数组 aa,但知道最终数组 bb。如果我们从最终状态反向推导,可以得到每个位置 ii 在初始时至少应该是多少。

    定义 lil_i 为位置 ii 在某个时刻必须满足的下界。初始时,最终状态要求 cibic_i \ge b_i,所以 l=bl = b


    反向操作规则

    考虑最后一次操作(第 qq 次):

    czq:=min(cxq,cyq)c_{z_q} := \min(c_{x_q}, c_{y_q})

    操作后,我们有 czqbzqc_{z_q} \ge b_{z_q},且 cxqbxqc_{x_q} \ge b_{x_q}cyqbyqc_{y_q} \ge b_{y_q}

    现在我们想知道操作前这些位置的下界。

    分析:

    • 对于 i{xq,yq,zq}i \notin \{x_q, y_q, z_q\},这些位置在操作中没有被修改,所以它们的下界不变:li=lil'_i = l_i
    • 对于 zqz_q:操作前 czqc_{z_q} 的值会被覆盖,所以操作前它没有任何限制(可以被任意值覆盖)。因此 lzq=0l'_{z_q} = 0
    • 对于 xqx_q:操作后 czq=min(cxq,cyq)c_{z_q} = \min(c_{x_q}, c_{y_q})
      由于 czqbzqc_{z_q} \ge b_{z_q},我们有 min(cxq,cyq)bzq\min(c_{x_q}, c_{y_q}) \ge b_{z_q}
      这意味着 cxqbzqc_{x_q} \ge b_{z_q}cyqbzqc_{y_q} \ge b_{z_q}
      另外,操作后 cxqc_{x_q} 保持不变,所以 cxqmax(bxq,bzq)c_{x_q} \ge \max(b_{x_q}, b_{z_q})
      同理 cyqmax(byq,bzq)c_{y_q} \ge \max(b_{y_q}, b_{z_q})

    因此,反向更新的规则是:

    $$l'_{x} = \max(l_x, l_z), \quad l'_{y} = \max(l_y, l_z) $$lz=0l'_z = 0

    其余位置不变。


    算法步骤

    1. 初始化:设 l=bl = b
    2. 逆向遍历操作 i=qi = q11
      • 记当前 lzil_{z_i}vv
      • lzil_{z_i} 设为 00(因为被覆盖)。
      • 更新 lxi=max(lxi,v)l_{x_i} = \max(l_{x_i}, v)
      • 更新 lyi=max(lyi,v)l_{y_i} = \max(l_{y_i}, v)
    3. 得到 ll 数组后,令 a=la = l
    4. 正向验证:用 aa 作为初始数组,按原操作顺序执行一遍,检查最终结果是否等于 bb
      • 如果相等,输出 aa
      • 如果不相等,输出 1-1

    为什么这样构造是正确的?

    • 必要性:任何可行的初始数组 aa 必须满足 ailia_i \ge l_i,否则无法达到 bb
    • 充分性:取 a=la = l 是满足条件的最小可能值。如果 a=la = l 经过正向操作后得到的结果不等于 bb,说明矛盾,无解。否则,a=la = l 就是一个解。

    时间复杂度

    • 逆向更新:O(q)O(q)
    • 正向模拟:O(q)O(q)
    • 总复杂度:O(n+q)O(n + q) 每个测试用例。

    代码实现

    // 逆向求出下界 l(存储在 c 数组中)
    for(int i = q ; i >= 1 ; i --){
        int v = c[z[i]];      // 当前 l[z_i] 的值
        c[z[i]] = 0;          // 被覆盖,下界变为 0
        c[x[i]] = max(c[x[i]], v);   // 更新 x_i 的下界
        c[y[i]] = max(c[y[i]], v);   // 更新 y_i 的下界
    }
    
    // a = l
    for(int i = 1 ; i <= n ; i ++) a[i] = c[i];
    
    // 正向模拟验证
    for(int i = 1 ; i <= q ; i ++) 
        c[z[i]] = min(c[x[i]], c[y[i]]);
    
    // 检查是否与 b 一致
    for(int i = 1 ; i <= n ; i ++) 
        if(b[i] != c[i]) {
            cout << "-1\n";
            return;
        }
    

    示例验证

    样例1:

    n=2, q=1, b=[1,2]
    操作: (2,1,2)
    

    逆向:

    • 初始 c=[1,2]c = [1,2]
    • i=1i=1: v=c[2]=2v = c[2] = 2c[2]=0c[2] = 0c[1]=max(1,2)=2c[1] = \max(1, 2) = 2a=[2,0]a = [2, 0] 正向:
    • c[2]=min(c[2],c[1])=min(0,2)=0c[2] = \min(c[2], c[1]) = \min(0, 2) = 0,最终 c=[2,0][1,2]c = [2, 0] \neq [1,2],输出 -1

    样例2:

    n=3, q=2, b=[1,2,3]
    操作1: (2,3,2)
    操作2: (1,2,1)
    

    逆向:

    • 初始 c=[1,2,3]c = [1,2,3]
    • i=2i=2: v=c[1]=1v = c[1] = 1c[1]=0c[1]=0c[1]=max(0,1)c[1]=\max(0,1)c[2]=max(2,1)=2c[2]=\max(2,1)=2
    • i=1i=1: v=c[2]=2v = c[2] = 2c[2]=0c[2]=0c[2]=max(0,2)c[2]=\max(0,2)c[3]=max(3,2)=3c[3]=\max(3,2)=3a=[1,2,3]a = [1,2,3] 正向模拟不改变数组,匹配 bb,输出 1 2 3

    总结

    本题的关键是逆向推导下界,然后正向验证。这种方法利用了 min\min 操作的性质,通过最大值传递约束,最终构造出最小可行解。如果最小解都不满足,则无解。

    • 1

    信息

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