1 条题解

  • 0
    @ 2025-12-4 17:59:46

    题目理解

    我们有 nn 支队伍,每支队伍 mm 个选手,队伍 ii 穿颜色 ii(即队伍编号就是颜色编号)。
    目标:经过若干次操作,让 ii 个空位 上的人穿颜色 aia_i


    操作

    • 选择 一支没有用过 的队伍 cc
    • 选择一个区间 [L,R][L, R]1LRm1 \le L \le R \le m)。
    • 从队伍 cc 里选 RL+1R-L+1 个人,放到位置 [L,R][L, R] 上,把原来这里的人挤走(完全覆盖)。
    • 每个队伍只能用一次。

    关键限制

    1. 每支队伍只能被用一次,所以最多有 nn 次操作。

    2. 每支队伍有 mm 个选手,所以一次操作区间长度 RL+1R-L+1 不能超过 mm(当然不会超过,因为位置最多 mm 个,其实这里是 RL+1mR-L+1 \le m,而且 mm 是固定的)。 仔细想:mm 是总空位数,也是每支队伍的人数。所以一次最多放 mm 个人到舞台上,这没问题,队伍有 mm 人,够用。

      其实真正限制是:操作区间长度不能超过 mm,但这里 mm 就是舞台长度,所以只能覆盖长度 m\le m 的区间——这其实没有约束,因为舞台上最大长度就是 mm,所以可以覆盖整个舞台。


    目标排列

    目标排列 a[1m]a[1\ldots m],每个 aja_j 是队伍编号(颜色编号),最终每个位置 jj 上的人颜色要是 aja_j


    思路分析

    因为我们每次操作会完全覆盖一个区间,把原来这里的人清掉,并且之后不能再用这支队伍,所以一个队伍的颜色在最终排列里可能出现在多个位置,但这些位置必须同时被该队伍覆盖成它的颜色,并且在那次操作之后,这些位置不能再被其他队伍改动(否则颜色就会变掉,除非其他队伍也穿同样颜色,但不同队伍颜色不同)。

    这意味着:
    如果颜色 cc 出现在 aa 的某些位置 p1,p2,,ptp_1, p_2, \dots, p_t,那么:

    • 必须有一次使用队伍 cc 的操作,区间 [L,R][L,R] 覆盖 {p1,,pt}\{p_1,\dots,p_t\} 的所有这些位置。
    • 在那之后,这些位置不能再被别的队伍覆盖。

    也就是说:每种颜色的所有出现位置,在最终操作序列里,必须是在同一次操作中被涂上这个颜色,并且之后这些位置不能变


    进一步抽象

    我们可以把舞台想象成一个长度为 mm 的数组,初始颜色未知(或者说是空的)。

    我们要用 nn 次区间覆盖操作,每次用不同的颜色(队伍),最终得到数组 aa

    因为每种颜色必须由该队伍一次完成所有出现位置的染色,所以不同颜色的出现位置集合不能交叉混合(因为如果交叉,就必须考虑操作的先后顺序:如果 A 颜色覆盖区间包含位置 ii,B 颜色覆盖区间也包含位置 ii,那么后操作的会覆盖先操作的,这样最终颜色是后者的。所以要想两者最终都保留,必须它们覆盖的位置集合不相交)。


    更严格来说: 设最终排列 aa
    对颜色 cc,令 Sc={jaj=c}S_c = \{j \mid a_j = c\}

    我们必须给每个颜色 cc 选择一个区间 [Lc,Rc][L_c, R_c],使得 Sc[Lc,Rc]S_c \subseteq [L_c, R_c],并且:

    • 所有颜色的这些区间在最终从后往前看(即按操作执行顺序的逆序)时,不同颜色的 ScS_c 集合对应的区间不冲突(即最终留下的颜色是最后一次覆盖它的颜色)。

    我们可以换个角度思考:按从后往前的构造顺序。

    假设最终颜色已经确定。我们想构造一个操作序列,最后一个操作的颜色,它的所有出现位置在最终状态里必须等于它的颜色;倒数第二个操作的颜色,它的所有出现位置中,没有被最后操作覆盖的位置,才是它的颜色……

    这其实就是 从后向前构造 的区间覆盖问题。


    可行性条件

    一个重要观察:
    最终排列 aa 中,如果颜色 cc 出现在多个位置,那么这些位置之间不能有其他颜色 dd 的位置,使得这些 dd 位置不完全被区间 [Lc,Rc][L_c,R_c] 覆盖的情况?
    让我们仔细推。

    考虑颜色 cc 的所有出现位置,它们的最小位置 mincmin_c最大位置 maxcmax_c
    因为队伍 cc 一次覆盖一个区间 [L,R][L,R],必须覆盖所有它的位置,所以必须有 LmincL \le min_cRmaxcR \ge max_c

    那么队伍 cc 覆盖的时候,会把 [L,R][L,R] 内原有的其他颜色全部清除掉,变成 cc
    所以对于任意其他颜色 dd,如果它的某个位置在 [L,R][L,R] 内,那么要么:

    1. ddcc 之后操作(即 dd 的操作在序列里更靠后,所以覆盖掉 cc 在那里的颜色),那么 dd 的区间也必须覆盖那个位置。
    2. 或者 ddcc 之前操作,那么 cc 会覆盖掉 dd 的那个位置,最终那里不是 dd,矛盾,除非 dd 的该位置最终不是 dd?不对,因为最终状态里颜色是固定的,如果最终 aj=ca_j = c,那么 dd 不能最终出现在 jj。所以如果 dd 的颜色出现在最终排列的 jj,并且 jjcc 的覆盖区间内,那么 dd 必须在 cc 之后操作,这样 dd 才会覆盖 ccjj 的颜色。

    因此对于最终颜色 dd 的每个位置 jj,以及任意其他颜色 cc,如果 j[Lc,Rc]j \in [L_c,R_c],则 dd 必须在 cc 之后操作。


    这引出一个偏序关系
    如果颜色 cc 的覆盖区间 [Lc,Rc][L_c,R_c] 和颜色 dd 的某个位置相交,则 dd 必须在 cc 之后操作。
    如果 cc 的区间完全包含 dd 的所有位置,那么 dd 必须在 cc 之后操作(因为 dd 的每个位置都被 cc 覆盖过,必须之后覆盖回来)。

    实际上,如果 mind,maxdmin_d, max_d[Lc,Rc][L_c,R_c] 内部(完全包含),那么 dd 必须在 cc 之后操作。
    但这 Lc,RcL_c, R_c 我们还没选,我们想尽可能让 cc 的区间就是 [minc,maxc][min_c, max_c](这样覆盖最少的多余位置)。

    所以设 Lc=mincL_c = min_c, Rc=maxcR_c = max_c


    结论条件

    那么,如果颜色 cc 的区间是 [minc,maxc][min_c, max_c],颜色 dd 的区间是 [mind,maxd][min_d, max_d]
    如果 [minc,maxc][min_c, max_c][mind,maxd][min_d, max_d] 相交但不包含,就会冲突。
    因为相交意味着某个颜色必须后操作,但如果只是部分相交,无法让两者都正确保留最终颜色

    我们来检查一下:假设 cc 先操作,覆盖 [minc,maxc][min_c, max_c]dd 后操作,覆盖 [mind,maxd][min_d, max_d],最终颜色:

    • 对于在 [mind,maxd][min_d, max_d] 中的位置,颜色是 dd(后覆盖)。
    • 因此 dd 的所有出现位置必须都在 [mind,maxd][min_d, max_d] 中,且 cc 的出现位置在 [minc,maxc][min_c, max_c] 中。
    • 如果 cc 的某个位置 pp 也在 [mind,maxd][min_d, max_d] 中,那么最终 apa_p 必须是 dd 而不是 cc,矛盾,除非 cc 不在那里出现。所以:如果 ccdd 的区间相交,那么它们的出现位置集合必须不相交

    因为 cc 的出现位置都在 [minc,maxc][min_c, max_c] 中,dd 的出现位置都在 [mind,maxd][min_d, max_d] 中,所以相交时出现位置集合无交。


    所以:
    可行当且仅当:不同颜色的出现位置的区间(最小位置到最大位置)要么不相交,要么一个完全包含另一个(形成嵌套)


    嵌套情况

    如果是包含关系,比如 [minc,maxc][min_c, max_c] 包含 [mind,maxd][min_d, max_d],那么谁先操作?
    如果 cc 先操作,会覆盖掉 dd 的位置,之后 dd 再操作覆盖回来,最终正确。
    如果 dd 先操作,之后 cc 覆盖掉 dd,最终 dd 的颜色没了,不行。
    所以包含关系中,外层必须先操作,内层后操作

    这给出一个操作顺序:按区间长度从大到小(即从外层到内层)操作。


    判断与构造

    所以算法步骤:

    1. 计算每种颜色 cc 的出现位置,得到 mincmin_cmaxcmax_c。如果颜色没出现,可以不用它。
    2. 检查任意两种颜色,如果区间相交,必须是一个包含另一个,否则无解(输出 -1)。
    3. 按区间长度从大到小排序颜色(外层先操作),构造操作顺序,每次操作区间就是 [minc,maxc][min_c, max_c]

    样例验证

    样例1:

    m=7, n=10
    a = 10 5 5 10 4 2 4
    

    颜色出现:

    • 10: 位置 1,4 → [1,4]
    • 5: 位置 2,3 → [2,3]
    • 4: 位置 5,7 → [5,7](注意这里 min=5, max=7)
    • 2: 位置 6 → [6,6]

    检查相交:

    • 10 和 5:10的区间 [1,4] 包含 5的区间 [2,3],OK。
    • 10 和 4:[1,4] 与 [5,7] 不相交,OK。
    • 10 和 2:[1,4] 与 [6,6] 不相交,OK。
    • 5 和 4:[2,3] 与 [5,7] 不相交,OK。
    • 5 和 2:[2,3] 与 [6,6] 不相交,OK。
    • 4 和 2:[5,7] 包含 [6,6],OK。

    按长度排序: 10:[1,4] 长度4 4:[5,7] 长度3 5:[2,3] 长度2 2:[6,6] 长度1

    操作顺序(外层先,即长度大的先): (10,1,4) (4,5,7) (5,2,3) (2,6,6)

    但题目给的样例操作是: 4 1 7 7 2 4 10 1 4 5 2 3 2 6 6

    这里队伍7颜色出现在哪?原排列 a 中没有7。样例用了额外的队伍(没出现过的颜色)来覆盖,说明我们可以用没出现过的颜色做中间覆盖,这样更灵活。

    这说明我们的“必须用该颜色一次覆盖所有它的位置”条件没错,但可以用其他颜色先覆盖大区间,然后内部再用目标颜色覆盖。这样构造可以更紧凑。


    更优构造方法

    已知:最终排列 aa,每个颜色出现位置集合 ScS_cminc,maxcmin_c, max_c

    构造方法(从后往前): 维护当前未覆盖的位置集合,从最后一个颜色开始,选择颜色 cc,覆盖 [minc,maxc][min_c, max_c](可能包含一些已经正确的其他颜色的位置,但那些位置会在之后被覆盖掉,因为我们是逆序构造)。

    具体步骤(正向输出时,顺序要反过来):

    1. 把所有颜色按 mincmin_c 排序。
    2. 用栈维护当前待处理的颜色区间,保证区间要么不相交,要么嵌套(否则无解)。
    3. 从栈底到栈顶,依次输出操作。

    • 1

    信息

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