题解:洛谷 AT_abc470_b Monocolor
【题目来源】
洛谷:AT_abc470_b [ABC470B] Monocolor
【题目描述】
有 \(N\) 个球。每个球都涂有 \(N\) 种颜色:颜色 \(1\) 到颜色 \(N\) 。第 \(i\) 个球第 \((1\le i\le N)\) 个球的颜色是 \(C_ i\) 。
只需一次操作,就可以将任意一个球的颜色更改为 \(N\) 中的任意一种颜色。
求使所有球的颜色相同所需的最少操作次数。
【输入】
输入内容由标准输入法提供,格式如下
\(N\)
\(C_1\) \(C_2\) \(\ldots\) \(C_N\)
【输出】
输出答案
【输入样例】
4
3 1 2 1
【输出样例】
2
【核心思想】
-
问题分析:给定 \(N\) 个球,每个球有颜色 \(C_i \in [1, N]\),每次操作可将任意一球改为任意颜色。求使所有球颜色相同的最少操作次数。这是一个贪心/模拟问题,核心观察是:最优策略是将所有球改为出现次数最多的颜色,这样需要改变的球数最少。
-
算法选择:
- 哈希表统计频率:用
map统计每种颜色出现的次数 - 贪心取最大频率:答案 = \(N - \max(\text{频率})\),即保留出现最多的颜色,其余全部修改
- 哈希表统计频率:用
-
关键步骤:
- 统计频率:遍历 \(C_1\) 到 \(C_N\),用
mp[x]++记录颜色 \(x\) 的出现次数 - 找最大频率:遍历
mp,找到出现次数最多的颜色次数 \(maxn\) - 计算答案:\(n - maxn\)(将非最大频率颜色的球全部改为该颜色)
- 统计频率:遍历 \(C_1\) 到 \(C_N\),用
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),遍历统计 + 遍历找最大值
- 空间复杂度:\(O(N)\),哈希表存储颜色频率
-
贪心策略的核心思想:
- 频率最大化原理:将所有球统一为某一种颜色时,选择出现次数最多的颜色作为目标色,需要修改的次数最少
- 操作等价性:每次操作只能改一个球的颜色,与改为什么颜色无关,因此只需最小化修改次数
- 鸽巢原理保证:\(N\) 个球 \(N\) 种颜色,必有至少一种颜色出现,但不一定有颜色重复
- 适用于众数问题、最小修改次数、颜色统一类问题
【算法标签】
入门 #模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, maxn=-1e9; // n:球的总数, maxn:出现次数最多的颜色的数量
map<int, int> mp; // mp[x]:颜色x出现的次数
int main()
{
cin >> n; // 读入球的总数
for (int i=1; i<=n; i++) // 循环读入每个球的颜色
{
int x; cin >> x; // 读入第i个球的颜色
mp[x]++; // 该颜色出现次数加1
}
// 遍历所有颜色,找出出现次数最多的颜色
for (auto t : mp)
maxn = max(maxn, t.second); // 更新最大出现次数
// 最少操作次数 = 总球数 - 出现次数最多的颜色的数量
// 即将其他所有球都改为该颜色
cout << n - maxn << endl;
return 0;
}
【运行结果】
4
3 1 2 1
2
浙公网安备 33010602011771号