【洛谷 P9421】[蓝桥杯 2023 国 B] 班级活动 题解(计数排序+贪心算法+数学)

[蓝桥杯 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 题


思路

首先,定义了一些常量和变量。其中,N 是数组的最大长度,n 是同学的数量,a 是存储同学ID的数组,cnt 是存储每个ID的数量的数组。xy 是两个计数器,表示需要匹配id的学生数量和需要改变id的学生数量。

读取学生的数量 n 和他们的ID a[i]。它使用一个数组 cnt[] 来计算每个ID的学生数量。

然后,它遍历 cnt[] 数组。对于每个ID i,如果有且仅有一个学生的ID为 i,则增加 x。这意味着这个学生需要匹配另一个学生的ID。如果有超过两个学生的ID相同,那么它将 y 增加 cnt[i] - 2。这意味着这些学生中的一部分需要改变他们的ID以匹配其他学生的ID。

如果一个ID只分配给了一个同学(x),那么这个同学需要找一个其他同学更改ID以形成一对。如果一个ID分配给了超过两个同学(y),那么这些同学中的一部分需要更改ID,使得每个ID只对应两个同学。在这个过程中,优先处理y,因为这些同学可以直接更改ID形成新的对,而不需要影响其他同学。

如果 x(需要匹配的学生数量)大于 y(需要改变的学生数量),那么输出 ((x - y) >> 1) + y。先让所有需要改变的学生都更改ID。剩下的部分中,每两个学生中只需要改变其中一人的ID就能匹配,所以需要除以2。

如果 x 小于或等于 y,那么输出 y,因为这些学生可以直接改变他们的ID以匹配其他学生。


AC代码

cpp 复制代码
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;

int n;
int a[N];
int cnt[N];

// 改别人的id
int x = 0;
// 自己要改id
int y = 0;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	memset(cnt, 0, sizeof(cnt));

	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		cnt[a[i]]++;
	}

	for (int i = 1; i <= n; i++) {
		if (cnt[i] == 1) {
			x++;
		} else if (cnt[i] > 2) {
			y += cnt[i] - 2;
		}
	}
	if (x > y) {
		cout << ((x - y) >> 1) + y << "\n";
	} else {
		cout << y << "\n";
	}
	return 0;
}
相关推荐
jiao_mrswang5 分钟前
leetcode-18-四数之和
算法·leetcode·职场和发展
Swift社区9 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Dong雨11 小时前
力扣hot100-->栈/单调栈
算法·leetcode·职场和发展
trueEve12 小时前
SQL,力扣题目1369,获取最近第二次的活动
算法·leetcode·职场和发展
ahadee12 小时前
蓝桥杯每日真题 - 第19天
c语言·vscode·算法·蓝桥杯
恃宠而骄的佩奇14 小时前
i春秋-签到题
web安全·网络安全·蓝桥杯
雨中rain15 小时前
贪心算法(1)
算法·贪心算法
ahadee16 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯
召木17 小时前
C++小白实习日记——Day 2 TSCNS怎么读取当前时间
c++·职场和发展
St_Ludwig17 小时前
C语言 蓝桥杯某例题解决方案(查找完数)
c语言·c++·后端·算法·游戏·蓝桥杯