题目大意

给定两个长度均为 nn 的序列 A,BA,B。你可以进行任意次如下操作:

  • 选择两个正整数 i,j[1,n]i,j \in [1,n],交换 Ai,AjA_i,A_j ,再交换 Bi,BjB_i,B_j

请最小化两个序列中逆序对个数之和。

解题思路

贪心方式:

先将 AA 序列由小到大排序,将 BB 以对应的下标重新排序,此时 AABB 的逆序对之和最小。

证明:

对于任意的两对元素 aia_iaja_jbib_ibjb_j,无论如何交换,他们之间对应的数永远是固定的,不难看出,每对数对于逆序对的贡献只有 0011 两种,则交换两对数对于逆序对的影响有三种:

  • 从贡献为 00 到贡献为 22

  • 从贡献为 22 到贡献为 00

  • 不变,贡献均为 11

通俗来说,只要让每对下标 iijj 中最多只有 11 个贡献,那么任何一对数的贡献都不会多于交换后的贡献。

那么应该如何做到呢,贪心的核心就在于排序,让 AA 序列由小到大排序,AA 中就不存在逆序对了,BB 中最多只有 11 个贡献,此时 BB​ 中的逆序对便是答案。

AC Code

1
2
3
4
5
6
7
8
9
void solve()
{
int n; cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i].first;
for (int i = 1; i <= n; i ++ ) cin >> a[i].second;
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++) cout << a[i].first << " \n"[i == n];
for (int i = 1; i <= n; i ++) cout << a[i].second << " \n"[i == n];
}