CF777B题解

发布时间 2023-10-27 11:36:02作者: Kazdale
  • 分析

    思考对于 \(M\) 的每个数而言,贡献是一定的,它最多只能换掉一个数。
    那么贪心地能换就换,但是如果换小的可能会导致更小的数换不掉,那么就换能换的最大的,这样不会干扰只能换小数的其他数,能换这个数的可以去换其他数,如果连其他数都换不掉说明这两个数等效,换谁都一样,所以这样换一定是最优的。
    如果一个数谁都换不掉,那么就不用给它配对,因为配谁都不会产生贡献,如果直接随便与一个换不掉的数配对的话就会发现当前换不掉的数可能会被其他数换掉,所以我们不匹配一个数也换不掉的数,默认它们与那些最后也不会被换掉的数匹配。

    发现对于两个要求换数的要求和询问对象是不一样的。
    第一个是要求 \(M\) 尽量不输,那么两个数如果相等也可以换,因为我们只是保证不输,然后最后输出最少的输的次数,即没换掉多少个 \(S\) 中的数。
    第二个是要求让 \(S\) 尽可能地输,那么只能换比自己小的数,因为我们想让对面输,然后输出最多的对面输的次数,即换掉了多少个 \(S\) 中的数。

  • 代码

#include <iostream>
#include <algorithm>
using namespace std;
constexpr int MAXN(1000007);
int a[MAXN], b[MAXN], vis[MAXN];
char c;
int n, ans;
inline void read(int &temp) { cin >> temp; }
int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	read(n);
	for (int i(1); i <= n; ++i) {
		cin >> c;
		a[i] = c - '0';
	}
	for (int i(1); i <= n; ++i) {
		cin >> c;
		b[i] = c - '0';
	}
	sort(a + 1, a + n + 1);
	ans = n;
	for (int i(1); i <= n; ++i)
		for (int j(n); j; --j)  if (!vis[j] && a[j] <= b[i])  { vis[j] = 1, --ans;  break; }
	cout << ans << endl;
	ans = 0; 
	for (int i(1); i <= n; ++i)  vis[i] = 0;
	for (int i(1); i <= n; ++i)
		for (int j(n); j; --j)  if (!vis[j] && a[j] < b[i])  { vis[j] = 1, ++ans;  break; }
	cout << ans << endl;
	return 0;
}