首先可以知道数组 A A A 和数组 B B B 的顺序均没有关系,所以我们首先将数组 A A A 和数组 B B B 进行排序,然后考虑两个数组的第一个元素。有以下两种情况:
首先我们可以知道,数组 A A A 和数组 B B B 的排列顺序不会影响最终的最大优势。
证明:如果在当前排列顺序下,数组 A A A 相对于数组 B B B 的优势已经取到了最大值,我们任意选取正整数 i , k i,k i,k ( 1 ≤ i , k ≤ n ) (1 \le i,k \le n ) (1≤i,k≤n),同时交换 A i A_i Ai 和 A k A_k Ak , B i B_i Bi 和 B k B_k Bk 的值,有三种情况:
如果交换之前满足 A i > B i A_i \gt B_i Ai>Bi 并且 A k ≤ B k A_k \le B_k Ak≤Bk ,那么交换后也必然满足 A k > B k A_k \gt B_k Ak>Bk 且 A i ≤ B i A_i \le B_i Ai≤Bi 。当 A i ≤ B i A_i \le B_i Ai≤Bi 并且 A k > B k A_k \gt B_k Ak>Bk 时,同理。
如果交换之前满足 A i ≤ B i A_i \le B_i Ai≤Bi 并且 A k ≤ B k A_k \le B_k Ak≤Bk,那么交换后也必然满足 A k ≤ B k A_k \le B_k Ak≤Bk 且 $A_i \le B_i $。
如果交换之前满足 A i > B i A_i \gt B_i Ai>Bi 并且 A k > B k A_k \gt B_k Ak>Bk,那么交换后也必然满足 A k > B k A_k \gt B_k Ak>Bk 且 A i > B i A_i \gt B_i Ai>Bi 。
可以发现我们改变了数组 A A A 和数组 B B B 的顺序,但是数组 A A A 相对于数组 B B B 的优势是不改变的。数组 A A A 和数组 B B B 的顺序是不会影响最终优势的。
思路的正确性在于:
对于第一种情况,由于 A A A 是有序的,那么 A A A 的任意元素大于 B B B 的首个元素:如果我们不与 B B B 的首个元素配对,由于 B B B 是有序的,之后的元素会更大,这样并不划算;如果我们与 B B B 的首个元素配对,我们使用 A A A 的首个元素,可以使得剩余的元素尽可能大,之后可以获得更多优势。
对于第二种情况,由于 B B B 是有序的,那么 A A A 的首个元素小于等于 B B B 中的任意元素,因此 A A A 的首个元素无法增加任何优势,可以直接移除。
在实际的代码编写中,我们不需要真正地移除元素。我们可以采用两个指针 p o s A pos_A posA 和 p o s B pos_B posB 分别指向数组 A A A 和数组 B B B 的首个元素,当需要移除元素时,直接 p o s + + pos ++ pos++ 即可。
#include
#include
using namespace std;
int n;
int A[100010], B[100010];
int main() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> A[i];
for (int i = 0; i < n; i ++) cin >> B[i];
sort(A, A + n); // c ++快速排序函数
sort(B, B + n);
int count = 0; // 记录优势数量
int pos_A = 0, pos_B = 0; // 分别指向 数组A 数组B 的第一个元素
for (; pos_A <= n; ) {
if ( A[pos_A] > B[pos_B] ) {
pos_A ++, pos_B ++; // 数组A和数组B的一个元素被"移除",新的第一个元素的下标为之前的pos+1,即pos ++
count ++; // 优势数量加一
} else pos_A ++; //数组A的一个元素被"移除"
}
cout << count;// 输出最大优势
return 0;
}