1 条题解
-
0
题目理解
我们有 支队伍,每支队伍 个选手,队伍 穿颜色 (即队伍编号就是颜色编号)。
目标:经过若干次操作,让 第 个空位 上的人穿颜色 。
操作:
- 选择 一支没有用过 的队伍 。
- 选择一个区间 ()。
- 从队伍 里选 个人,放到位置 上,把原来这里的人挤走(完全覆盖)。
- 每个队伍只能用一次。
关键限制
-
每支队伍只能被用一次,所以最多有 次操作。
-
每支队伍有 个选手,所以一次操作区间长度 不能超过 (当然不会超过,因为位置最多 个,其实这里是 ,而且 是固定的)。 仔细想: 是总空位数,也是每支队伍的人数。所以一次最多放 个人到舞台上,这没问题,队伍有 人,够用。
其实真正限制是:操作区间长度不能超过 ,但这里 就是舞台长度,所以只能覆盖长度 的区间——这其实没有约束,因为舞台上最大长度就是 ,所以可以覆盖整个舞台。
目标排列
目标排列 ,每个 是队伍编号(颜色编号),最终每个位置 上的人颜色要是 。
思路分析
因为我们每次操作会完全覆盖一个区间,把原来这里的人清掉,并且之后不能再用这支队伍,所以一个队伍的颜色在最终排列里可能出现在多个位置,但这些位置必须同时被该队伍覆盖成它的颜色,并且在那次操作之后,这些位置不能再被其他队伍改动(否则颜色就会变掉,除非其他队伍也穿同样颜色,但不同队伍颜色不同)。
这意味着:
如果颜色 出现在 的某些位置 ,那么:- 必须有一次使用队伍 的操作,区间 覆盖 的所有这些位置。
- 在那之后,这些位置不能再被别的队伍覆盖。
也就是说:每种颜色的所有出现位置,在最终操作序列里,必须是在同一次操作中被涂上这个颜色,并且之后这些位置不能变。
进一步抽象
我们可以把舞台想象成一个长度为 的数组,初始颜色未知(或者说是空的)。
我们要用 次区间覆盖操作,每次用不同的颜色(队伍),最终得到数组 。
因为每种颜色必须由该队伍一次完成所有出现位置的染色,所以不同颜色的出现位置集合不能交叉混合(因为如果交叉,就必须考虑操作的先后顺序:如果 A 颜色覆盖区间包含位置 ,B 颜色覆盖区间也包含位置 ,那么后操作的会覆盖先操作的,这样最终颜色是后者的。所以要想两者最终都保留,必须它们覆盖的位置集合不相交)。
更严格来说: 设最终排列 。
对颜色 ,令 。我们必须给每个颜色 选择一个区间 ,使得 ,并且:
- 所有颜色的这些区间在最终从后往前看(即按操作执行顺序的逆序)时,不同颜色的 集合对应的区间不冲突(即最终留下的颜色是最后一次覆盖它的颜色)。
我们可以换个角度思考:按从后往前的构造顺序。
假设最终颜色已经确定。我们想构造一个操作序列,最后一个操作的颜色,它的所有出现位置在最终状态里必须等于它的颜色;倒数第二个操作的颜色,它的所有出现位置中,没有被最后操作覆盖的位置,才是它的颜色……
这其实就是 从后向前构造 的区间覆盖问题。
可行性条件
一个重要观察:
最终排列 中,如果颜色 出现在多个位置,那么这些位置之间不能有其他颜色 的位置,使得这些 位置不完全被区间 覆盖的情况?
让我们仔细推。考虑颜色 的所有出现位置,它们的最小位置 ,最大位置 。
因为队伍 一次覆盖一个区间 ,必须覆盖所有它的位置,所以必须有 且 。那么队伍 覆盖的时候,会把 内原有的其他颜色全部清除掉,变成 。
所以对于任意其他颜色 ,如果它的某个位置在 内,那么要么:- 在 之后操作(即 的操作在序列里更靠后,所以覆盖掉 在那里的颜色),那么 的区间也必须覆盖那个位置。
- 或者 在 之前操作,那么 会覆盖掉 的那个位置,最终那里不是 ,矛盾,除非 的该位置最终不是 ?不对,因为最终状态里颜色是固定的,如果最终 ,那么 不能最终出现在 。所以如果 的颜色出现在最终排列的 ,并且 在 的覆盖区间内,那么 必须在 之后操作,这样 才会覆盖 在 的颜色。
因此对于最终颜色 的每个位置 ,以及任意其他颜色 ,如果 ,则 必须在 之后操作。
这引出一个偏序关系:
如果颜色 的覆盖区间 和颜色 的某个位置相交,则 必须在 之后操作。
如果 的区间完全包含 的所有位置,那么 必须在 之后操作(因为 的每个位置都被 覆盖过,必须之后覆盖回来)。实际上,如果 在 内部(完全包含),那么 必须在 之后操作。
但这 我们还没选,我们想尽可能让 的区间就是 (这样覆盖最少的多余位置)。所以设 , 。
结论条件
那么,如果颜色 的区间是 ,颜色 的区间是 ,
如果 和 相交但不包含,就会冲突。
因为相交意味着某个颜色必须后操作,但如果只是部分相交,无法让两者都正确保留最终颜色。我们来检查一下:假设 先操作,覆盖 , 后操作,覆盖 ,最终颜色:
- 对于在 中的位置,颜色是 (后覆盖)。
- 因此 的所有出现位置必须都在 中,且 的出现位置在 中。
- 如果 的某个位置 也在 中,那么最终 必须是 而不是 ,矛盾,除非 不在那里出现。所以:如果 和 的区间相交,那么它们的出现位置集合必须不相交。
因为 的出现位置都在 中, 的出现位置都在 中,所以相交时出现位置集合无交。
所以:
可行当且仅当:不同颜色的出现位置的区间(最小位置到最大位置)要么不相交,要么一个完全包含另一个(形成嵌套)。
嵌套情况
如果是包含关系,比如 包含 ,那么谁先操作?
如果 先操作,会覆盖掉 的位置,之后 再操作覆盖回来,最终正确。
如果 先操作,之后 覆盖掉 ,最终 的颜色没了,不行。
所以包含关系中,外层必须先操作,内层后操作。这给出一个操作顺序:按区间长度从大到小(即从外层到内层)操作。
判断与构造
所以算法步骤:
- 计算每种颜色 的出现位置,得到 和 。如果颜色没出现,可以不用它。
- 检查任意两种颜色,如果区间相交,必须是一个包含另一个,否则无解(输出 -1)。
- 按区间长度从大到小排序颜色(外层先操作),构造操作顺序,每次操作区间就是 。
样例验证
样例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。样例用了额外的队伍(没出现过的颜色)来覆盖,说明我们可以用没出现过的颜色做中间覆盖,这样更灵活。
这说明我们的“必须用该颜色一次覆盖所有它的位置”条件没错,但可以用其他颜色先覆盖大区间,然后内部再用目标颜色覆盖。这样构造可以更紧凑。
更优构造方法
已知:最终排列 ,每个颜色出现位置集合 ,。
构造方法(从后往前): 维护当前未覆盖的位置集合,从最后一个颜色开始,选择颜色 ,覆盖 (可能包含一些已经正确的其他颜色的位置,但那些位置会在之后被覆盖掉,因为我们是逆序构造)。
具体步骤(正向输出时,顺序要反过来):
- 把所有颜色按 排序。
- 用栈维护当前待处理的颜色区间,保证区间要么不相交,要么嵌套(否则无解)。
- 从栈底到栈顶,依次输出操作。
- 1
信息
- ID
- 5779
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者