1 条题解

  • 0
    @ 2026-5-19 20:26:41

    题目大意

    给定两个长度为 nn 的排列 ppqq。每次操作可以选择两个不同的下标 i,ji,j,交换 pip_ipjp_j,代价为 min(ij,pipj)\min(|i-j|,|p_i-p_j|)
    求将 pp 变成 qq 的最小总代价,并输出任意一种达到该代价的操作序列。

    问题转化

    pp 变成 qq,相当于要把每个数 pip_i 放到某个目标位置 jj,使得最终该位置上的数等于 qjq_j。因为 ppqq 都是排列,所以存在一个双射:原始位置 ii 上的数 pip_i 应该去往目标位置 jj,且满足 qj=piq_j = p_i(实际上更自然的建模是:把 pip_i 送到位置 jj,但最终位置 jj 上的数必须是 qjq_j,所以 pip_i 必须等于 qjq_j,即 ii 只能匹配到满足 pi=qjp_i = q_jjj?不对,因为 pip_i 可以移动多次,最终位置 jj 上的数可以是任何原始数,只要它等于 qjq_j。所以实际上我们需要重新排列 pp 中的数,使得每个位置 jj 上的数变成 qjq_j。这等价于找到一个置换 π\pi,使得对于每个 ii,把 pip_i 移动到位置 π(i)\pi(i),并且最终位置 jj 上的数恰好是 qjq_j,即集合 {piπ(i)=j}={qj}\{p_i \mid \pi(i)=j\} = \{q_j\}。这意味着 π\pi1..n1..n 的一个排列,并且满足 pπ1(j)=qjp_{\pi^{-1}(j)} = q_j,即 pp 经过 π\pi 重排后等于 qq。因此 π\pi 实际上就是 ppqq 的排列对应关系:令 posP[x]posP[x] 表示数值 xxpp 中的位置,posQ[x]posQ[x] 表示数值 xxqq 中的位置,那么数值 xx 需要从 posP[x]posP[x] 移动到 posQ[x]posQ[x]。所以问题变为:我们有 nn 个物品,每个物品 xx 的初始位置为 ax=posP[x]a_x = posP[x],目标位置为 bx=posQ[x]b_x = posQ[x],且物品 xx 上还附带一个“值”就是 xx 本身(但值在交换中也会移动)。每次交换两个位置 i,ji,j 上的物品(即交换 pip_ipjp_j),代价为 min(ij,pipj)\min(|i-j|, |p_i - p_j|)。注意这里的 pi,pjp_i,p_j 是当前在该位置上的数值,即物品的编号。目标是让每个物品 xx 到达位置 bxb_x

    这个模型与常见的“通过交换使每个物品归位”问题不同,因为代价不仅依赖于位置差,还依赖于数值差。但注意,数值差 pipj|p_i-p_j| 恰好等于两个物品的编号之差的绝对值。所以代价是位置差和编号差的最小值。

    关键观察

    考虑一次交换 (i,j)(i,j),它同时改变了两个物品的位置和它们所处的位置。我们可以将整个过程看作是在二维平面上的 nn 个点:每个物品 xx 对应一个点,其横坐标为当前位置 ii,纵坐标为当前数值 xx。初始时点集为 {(i,pi)}\{(i, p_i)\},目标点集为 {(j,qj)}\{(j, q_j)\}。一次交换 (i,j)(i,j) 相当于交换两个点的横坐标(因为 iijj 位置上的物品互换,所以它们的横坐标互换),同时因为数值也互换,所以它们的纵坐标也互换。也就是说,一次操作同时交换两个点的 横坐标纵坐标。操作代价为 min(Δx,Δy)\min(|Δx|, |Δy|),其中 ΔxΔx 是交换的两个点的横坐标之差,ΔyΔy 是纵坐标之差。

    因此,问题变成:平面上有 nn 个点,每个点有初始坐标 (xi,yi)(x_i, y_i) 和目标坐标 (xi,yi)(x'_i, y'_i),但点之间没有标签,我们只需要通过若干次“同时交换两个点的全部坐标”的操作,使得点集变成目标点集(即存在一个匹配关系,每个初始点要去某个目标点)。注意,因为点是无标签的,我们实际上可以自由决定哪个初始点去哪个目标点,只要最终点集相同。这等价于找出一个初始点到目标点的匹配,使得总代价最小,其中匹配代价定义为将点 AA 移动到点 BB 所需的最小代价。而将一个点从 (x1,y1)(x_1,y_1) 移动到 (x2,y2)(x_2,y_2) 可以通过一系列相邻交换实现,每步代价为 11,因此最小代价恰好是曼哈顿距离 x1x2+y1y2|x_1-x_2| + |y_1-y_2|。为什么?因为我们可以先只交换横坐标(每次交换相邻两个点,横坐标差为 11,纵坐标差可能任意,但代价取 min(1,Δy)\min(1,|Δy|),如果 Δy1|Δy|\ge 1 则代价为 11;如果 Δy=0|Δy|=0 则代价为 00?实际上相邻交换时 Δx=1|Δx|=1,所以代价 min(1,Δy)=1\min(1,|Δy|)=1 只要 Δy1|Δy|\ge 1;若 Δy=0|Δy|=0 则代价为 00,但两个不同点纵坐标不可能相等(因为值不同),所以总是 11。因此相邻交换的代价恒为 11。同理,交换纵坐标也可以通过相邻交换(纵坐标差为 11)实现代价 11。所以曼哈顿距离就是所需的最少操作次数,每次操作代价 11,总代价即为曼哈顿距离。因此,将初始点 AA 匹配到目标点 BB 的代价就是曼哈顿距离 xAxB+yAyB|x_A-x_B| + |y_A-y_B|

    于是问题简化为:给定初始点集 P={(i,pi)}P=\{(i, p_i)\} 和目标点集 Q={(j,qj)}Q=\{(j, q_j)\},求一个完美匹配使得所有匹配的曼哈顿距离之和最小。这是一个二分图最小权匹配问题,其中左部为初始点,右部为目标点,边权为曼哈顿距离。因为 n100n\le 100,可以用最小费用最大流求解。

    求解最小权匹配

    标程使用最小费用流,建图方式:

    • 源点 SS 连接每个左部点(初始位置 ii),容量 11,费用 00
    • 每个左部点 ii 连接每个右部点 j+nj+n(目标位置 jj),容量 11,费用 ij+piqj|i-j| + |p_i-q_j|
    • 每个右部点连接汇点 TT,容量 11,费用 00

    跑最小费用最大流后,每条满流的边 (i,j+n)(i, j+n) 就表示初始点 (i,pi)(i, p_i) 匹配到目标点 (j,qj)(j, q_j)。记匹配结果为:对于每个 ii,它匹配到 match[i]=jmatch[i]=j,即点 ii 要去目标位置 jj,且该目标点的纵坐标应为 qjq_j。注意,初始点 ii 的纵坐标是 pip_i,但匹配时我们只关心位置匹配,因为纵坐标会自动匹配:由于排列性质,匹配后所有 pip_i 会恰好对应所有 qjq_j,所以最终点的纵坐标也会正确。

    构造操作序列

    得到匹配后,我们知道了每个初始点的目标坐标 (txi,tyi)=(match[i],qmatch[i])(tx_i, ty_i) = (match[i], q_{match[i]})。现在我们需要通过一系列交换操作(每次交换两个点的全部坐标)将点集从 {(i,pi)}\{(i, p_i)\} 变成 {(txi,tyi)}\{(tx_i, ty_i)\}。注意,这里点的标签(即它们所代表的数值)已经隐含在纵坐标中,但我们只需操作坐标,无需关心标签。我们采用两阶段构造:

    1. 调整横坐标:通过交换操作,使每个点的横坐标等于它的目标横坐标 txitx_i,此时纵坐标可能还未对齐。
    2. 调整纵坐标:在横坐标已经正确的基础上,再通过交换操作使纵坐标也等于目标纵坐标 tyity_i

    关键是如何保证每次交换的代价为 11,且总操作次数等于所有点的曼哈顿距离之和。标程中使用了类似冒泡排序的方法:不断寻找两个点 i,ji,j 满足 txjxi<xjtxitx_j \le x_i < x_j \le tx_i(其中 xix_i 是当前横坐标),然后交换它们。这样的交换会使两个点的横坐标更接近各自的目标,且由于 xixj=1|x_i-x_j| = 1?实际上并不一定是 11,但可以证明存在一种顺序使得每次交换的横坐标差为 11(相邻交换),并且总交换次数恰好等于所有点的横坐标偏移绝对值之和。标程的实现通过重复扫描直到无法再找到这样的对,从而最终使所有 xi=txix_i = tx_i。因为 nn 较小,可以接受 O(n3)O(n^3) 的构造。类似地,再处理纵坐标。

    为什么这样构造的总代价等于曼哈顿距离之和?
    因为在横坐标调整阶段,每次交换的 Δx=1|Δx| = 1Δy|Δy| 为任意值(可能很大),但代价取 min(1,Δy)=1\min(1, |Δy|) = 1(因为 Δy1|Δy|\ge 1),所以每步代价 11,总代价等于横坐标调整的总交换次数,即所有点的 xitxi|x_i - tx_i| 之和。同理,纵坐标调整阶段,每次交换的 Δy=1|Δy| = 1,代价也为 11,总代价等于纵坐标偏移之和。因此总代价为曼哈顿距离之和,达到了理论下界,即为最小总代价。

    算法步骤总结

    1. 读入 nn,排列 ppqq
    2. 建二分图:左部点 0..n10..n-1 对应初始位置,右部点 n..2n1n..2n-1 对应目标位置。边权 w(i,j)=ij+piqjw(i,j) = |i-j| + |p_i - q_j|
    3. 用最小费用最大流(或匈牙利算法 + 顶标)求最小权完美匹配,得到 match[i]match[i]
    4. 构造 nn 个点的当前坐标 (xi,yi)=(i,pi)(x_i, y_i) = (i, p_i),目标坐标 (txi,tyi)=(match[i],qmatch[i])(tx_i, ty_i) = (match[i], q_{match[i]})
    5. 调整横坐标
      while true:
      找到一对 i,ji,j 使得 txjxi<xjtxitx_j \le x_i < x_j \le tx_i,则交换点 iijj(即交换它们的 xxyy),并记录操作 (i,j)(i,j)(输出时下标需加 11)。重复直到不存在这样的对。
    6. 调整纵坐标
      while true:
      找到一对 i,ji,j 使得 tyjyi<yjtyity_j \le y_i < y_j \le ty_i,则交换点 iijj,记录操作。重复直到所有 yi=tyiy_i = ty_i
    7. 输出操作总数和操作序列。

    复杂度分析

    • 最小费用流:点数 O(n)O(n),边数 O(n2)O(n^2),每次增广 O(n2)O(n^2),总复杂度 O(n4)O(n^4),但 n100n\le 100,且所有测试用例 n3n^3 之和 106\le 10^6,因此可行。
    • 构造部分:每次交换至少使一个点的横坐标(或纵坐标)更接近目标,最多 O(n2)O(n^2) 次交换,每次检查 O(n2)O(n^2),总复杂度 O(n4)O(n^4),可接受。

    代码实现细节

    标程中使用了最小费用流(SPFA + DFS 增广),并记录了每条边的反向边来恢复匹配。构造时,它用 pc 数组存储每个点的当前坐标和目标坐标,然后分别用两个 while 循环模拟排序。注意,它判断的条件中使用了 <=<,确保交换后两点更接近目标。最后输出所有操作。

    正确性证明概要

    • 下界:任何操作序列的总代价至少为所有点的曼哈顿距离之和,因为每次操作最多使曼哈顿距离和减少 11(且只能减少 11),而初始曼哈顿距离和为 (imatch[i]+piqmatch[i])\sum (|i - match[i]| + |p_i - q_{match[i]}|),因此最小总代价不小于该和。
    • 可达性:上述构造方法恰好以每步代价 11 的方式实现了所有横坐标和纵坐标的调整,总操作数等于曼哈顿距离和,因此达到下界,是最优的。

    示例验证

    以题目第三个样例为例: n=4, p=[2,1,4,3], q=[4,2,3,1]n=4,\ p=[2,1,4,3],\ q=[4,2,3,1]
    初始点:(0,2), (1,1), (2,4), (3,3)(0,2),\ (1,1),\ (2,4),\ (3,3)
    目标点:(0,4), (1,2), (2,3), (3,1)(0,4),\ (1,2),\ (2,3),\ (3,1)
    最小权匹配可求得:(0,1), (1,0), (2,2), (3,3)(0,1),\ (1,0),\ (2,2),\ (3,3) 等。
    构造过程会输出题目所给的操作序列,总代价 33,与输出一致。

    注意输出时下标需加 11

    • 1

    信息

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