【洛谷 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;
}
相关推荐
江畔柳前堤3 小时前
Go04-控制结构
大数据·人工智能·面试·职场和发展·go·业界资讯
wdfk_prog10 小时前
嵌入式面试真题第 10 题:高优化等级下共享状态可见性、内存模型与系统级同步设计
java·linux·开发语言·面试·职场和发展·架构·c
wdfk_prog12 小时前
嵌入式面试真题第 11 题:RTOS 优先级翻转与实时任务阻塞的通用治理
c语言·缓存·面试·职场和发展·架构
晚笙coding20 小时前
LeetCode 226. 翻转二叉树(Invert Binary Tree)
算法·leetcode·职场和发展
天才测试猿1 天前
如何封装自动化测试框架?
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
恣逍信点2 天前
《凌微经》通俗解读——哲学第一因
学习·职场和发展·创业创新·学习方法·业界资讯·交友·哲学
怪兽学LLM3 天前
LeetCode 105. 从前序与中序遍历序列构造二叉树:分治递归思路详解
算法·leetcode·职场和发展
QQ骞3 天前
【ECU-HIL 嵌入式车载软件测试学习路线和面试描述方式(1)】
学习·面试·职场和发展
Scabbards_3 天前
面试Leetcode - Array
leetcode·面试·职场和发展