最大优势(1e5)_题解

【题解提供者】张俊豪

解法

思路

首先可以知道数组 A A A 和数组 B B B 的顺序均没有关系,所以我们首先将数组 A A A 和数组 B B B 进行排序,然后考虑两个数组的第一个元素。有以下两种情况:

  1. 如果数组 A A A 的首个元素大于数组 B B B 的首个元素,那么就将它看作一对,并计算一点优势,同时从数组中移除这两个元素。
  2. 如果数组 A A A 的首个元素小于等于数组 B B B 的首个元素 那么就移除数组 A A A 中的首个元素。

分析

首先我们可以知道,数组 A A A 和数组 B B B 的排列顺序不会影响最终的最大优势。

证明:如果在当前排列顺序下,数组 A A A 相对于数组 B B B 的优势已经取到了最大值,我们任意选取正整数 i , k i,k ik ( 1 ≤ i , k ≤ n ) (1 \le i,k \le n ) 1ikn),同时交换 A i A_i Ai A k A_k Ak B i B_i Bi B k B_k Bk 的值,有三种情况:

  1. 如果交换之前满足 A i > B i A_i \gt B_i Ai>Bi 并且 A k ≤ B k A_k \le B_k AkBk ,那么交换后也必然满足 A k > B k A_k \gt B_k Ak>Bk A i ≤ B i A_i \le B_i AiBi 。当 A i ≤ B i A_i \le B_i AiBi 并且 A k > B k A_k \gt B_k Ak>Bk 时,同理。

  2. 如果交换之前满足 A i ≤ B i A_i \le B_i AiBi 并且 A k ≤ B k A_k \le B_k AkBk,那么交换后也必然满足 A k ≤ B k A_k \le B_k AkBk 且 $A_i \le B_i $。

  3. 如果交换之前满足 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; 
}

你可能感兴趣的:(算法,数据结构,c++)