【洛谷 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;
}
相关推荐
Frostnova丶3 小时前
(13)LeetCode 53. 最大子数组和
算法·leetcode·职场和发展
tkevinjd13 小时前
力扣437路径总和III
算法·leetcode·面试·职场和发展
Frostnova丶20 小时前
(12)LeetCode 76. 最小覆盖子串
算法·leetcode·职场和发展
旧曲重听121 小时前
为什么现在 RAG 越少越少提及了
数据库·程序人生·职场和发展·agent
凯瑟琳.奥古斯特1 天前
力扣1013三等分解法与C++实现
开发语言·c++·算法·leetcode·职场和发展
变量未定义~1 天前
单调栈、单调队列(模板)、子矩阵(模板)
数据结构·算法·蓝桥杯
bukeyiwanshui1 天前
20260701 k8s Metric Server
容器·贪心算法·kubernetes
凯瑟琳.奥古斯特1 天前
力扣1012数位DP解法详解
开发语言·c++·算法·leetcode·职场和发展
Robot_Nav1 天前
贪心算法、动态规划与 MPPI 算法结构相关力扣题目汇总
算法·贪心算法·动态规划
June bug1 天前
【199管理类联考】写作(第一轮复习)
考研·职场和发展·学习方法