藍橋杯-班級活動

小程xy發表於2024-05-23

題目描述

小明的老師準備組織一次班級活動。班上一共有 ( n ) 名(( n ) 為偶數)同學,老師想把所有的同學進行分組,每兩名同學一組。為了公平,老師給每名同學隨機分配了一個 ( n ) 以內的正整數作為 id,第 ( i ) 名同學的 id 為 ( a_i )。

老師希望透過更改若干名同學的 id 使得對於任意一名同學 ( i ),有且僅有另一名同學 ( j ) 的 id 與其相同(( a_i = a_j ))。請問老師最少需要更改多少名同學的 id?

輸入格式

輸入共 2 行。

第一行為一個正整數 ( n )。

第二行為 ( n ) 個由空格隔開的整數 ( a_1, a_2, ..., a_n )。

輸出格式

輸出共 1 行,一個整數。

輸入輸出樣例

輸入 #1

4
1 2 2 3

輸出 #1

1

說明/提示

樣例說明
僅需要把 ( a_1 ) 改為 3 或者把 ( a_4 ) 改為 1 即可。

評測用例規模與約定

  • 對於 20% 的資料,保證 ( n <= 10^3 )。
  • 對於 100% 的資料,保證 ( n <= 10^5 )。

題解:

一共有兩種情況

  1. 只出現過一次的id個數 cnt1 >= 出現過2次以上的id個數 cnt2。 此時把 所有cnt2 都更改成一個id只出現過一次的, 再加上剩下的 cnt1 / 2
  2. 只出現過一次的id個數 cnt1 < 出現過2次以上的id個數 cnt2。 此時把 cnt1個cnt2 都改成一個id只出現過一次的, 再加上剩下的 cnt2 /2

ps: 說白了就是 當有cnt1的時候, 儘可能把cnt2變成cnt1, 當cnt2有剩餘的話, 還需要改變 "剩餘的cnt2的個數" 次, 當cnt1有剩餘的話, 還需要改變 "剩餘的cnt1的個數 / 2"

ac程式碼👇

#include <bits/stdc++.h>
using namespace std;

unordered_map<int,int> mp;
int main()
{
	int n; cin >> n;
	for (int i = 0; i < n; i ++) 
	{
		int x; cin >> x;
		mp[x] ++;
	}
	int cnt1 = 0, cnt2 = 0;
	for (auto it : mp)
	{
		if (it.second == 1) cnt1 ++;  // id出現過一次的個數
		if (it.second > 2) cnt2 += it.second - 2;  // id出現次數大於2的都要改成別的id
	}
	if (cnt2 - cnt1 >= 0) cout << cnt1 + (cnt2 - cnt1) << endl;  // 情況1
	else  cout << cnt2 + (cnt1 - cnt2) / 2 << endl;    // 情況2
	return 0;	
}

覺得寫的不錯的話, 點個贊吧~