[蓝桥杯 2023 国 B] 班级活动
题目描述
小明的老师准备组织一次班级活动。班上一共有 n n n 名( n n n 为偶数)同学,老师想把所有的同学进行分组,每两名同学一组。为了公平,老师给每名同学随机分配了一个 n n n 以内的正整数作为 id,第 i i i 名同学的 id 为 a i a_i ai。
老师希望通过更改若干名同学的 id 使得对于任意一名同学 i i i,有且仅有另一名同学 j j j 的 id 与其相同( a i = a j a_i = a_j ai=aj)。请问老师最少需要更改多少名同学的 id?
输入格式
输入共 2 2 2 行。
第一行为一个正整数 n n n。
第二行为 n n n 个由空格隔开的整数 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an。
输出格式
输出共 1 1 1 行,一个整数。
样例 #1
样例输入 #1
4
1 2 2 3
样例输出 #1
1
提示
样例说明
仅需要把 a 1 a_1 a1 改为 3 3 3 或者把 a 4 a_4 a4 改为 1 1 1 即可。
评测用例规模与约定
- 对于 20 % 20\% 20% 的数据,保证 n ≤ 1 0 3 n \le 10^3 n≤103。
- 对于 100 % 100\% 100% 的数据,保证 n ≤ 1 0 5 n \le 10^5 n≤105。
第十四届蓝桥杯大赛软件赛决赛 C/C++ 大学 B 组 C 题
思路
模拟人脑来思考这个问题,当我们看到一串数字时,会先去配对已经配对好的数据,也就是将已经成对的数据匹配出来,然后对于剩下的数据,有两种情况:
- 情况1:该数据为多出来的,例如 1 1 1 1,前面两个1配队,后面两个1就是多出来的
- 情况2:该数据为缺少配队的:例如1 2 3 4,这四个数据都是缺少配队的。
那么我们对于剩下的这些数据,会先尝试将多出来的数据与缺少配队的进行修改配队,这样能保证修改次数最小,这个时候修改的次数为两者差的绝对值,之后,又出现两种情况:
- 情况1:剩余的是多出的数据
- 情况2:剩余的是缺少的数据
对于这两种情况的数据,我们分别处理:
- 多出的数据:例如1 1,这两个数据都需要去修改,因此产生的修改次数为 多出的数据个数
- 缺少的数据:例如1 2,这两个数据只需要修改一个就可以,因此修改的次数为 缺少的数据个数/2
关于数据处理问题,我们用桶去记录个数,用 lessnum
记录缺少的数据,用 morenum
记录多出的数据,每读取一个值后,下标为 i
的数据个数有以下三种情况:
- 等于2
- 小于2
- 大于2
分别有如下三种方式对应处理:
- 等于2:说明有一个缺少的数据被配齐了,
lessnum-=1
- 小于2:说明出现了一个缺少的数据,
lessnum+=1
- 大于2:说明出现了一个多出的数据,
morenum+=1
思路清晰了就可以写代码了:
// Problem: P9421 [蓝桥杯 2023 国 B] 班级活动
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P9421
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)/*************************************************************************> Author: Royi > Mail: royi990001@gmail.com > From: > Language: C/C++************************************************************************/#include <bits/stdc++.h>
using namespace std;
using ll = long long;const int MAX_N = 1e5 + 100;int a[MAX_N];
int lessnum = 0, morenum = 0;void solve() {int n, l = 1, r = 1;cin >> n;for (int i = 1, temp; i <= n; i++) {cin >> temp;a[temp]++;if (a[temp] == 2) {--lessnum;continue;}if (a[temp] < 2) {++lessnum;} else {++morenum;}//cout << "i = " << i << " morenum = " << morenum << " lessnum = " << lessnum << '\n';}int ans = 0;if (morenum == lessnum) {ans = (morenum + lessnum) >> 1;} else if (morenum == 0 || lessnum == 0) {if (morenum == 0) {ans = lessnum / 2;} else {ans = morenum;}} else {if (morenum > lessnum) {ans += lessnum;morenum -= lessnum;ans += morenum;} else {ans += morenum;lessnum -= morenum;ans += (lessnum >> 1);}}cout << ans << '\n';return ;
}int main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);solve();return 0;
}