题干真TM难懂……a里面的元素是乐队的编号,a反映的是乐队出场次数和顺序(顺序不重要,关键是次数),也就是说一个编号在a里面出现了多少次,它就上场了多少次,b[x] = y的意思是Polycarp喜欢的乐队x出场y次,这里x是他超喜欢的乐队的名字的编号,他想要改变a使他喜欢的乐队中出演的最少次数最大,也就是说每个b[i] >= per,这个per尽可能大,什么时候per最大,当然是均值n / m的时候
有一个注意的地方就是例如:
7 3
1 3 2 4 2 2 1
7 / 3 = 2,到底是把4变成3还是把一个2变成3,其实无所谓,最后min(b[1], b[2], b[3])都是等于2,虽然把4变成3确实使喜欢的乐队总数多,但是题目要求的是最少的出场次数最大,并不是总体数目尽量多,还有就是比如变一个2为3,则成为1 3 3 4 2 2 1,还有没有必要继续变4为1,2,3其中之一?没必要,因为就算变了,min(b[1], b[2], b[3])还是为2,还白白多加了一次变换次数,题目要求出场次数最小值尽可能大的同时,还要求改变次数尽可能小
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
int n, m, per, cnt;
int a[2005];
map<int, int> mp;
int main()
{
cin >> n >> m;
per = n / m;
mp.clear();
for (int i = 1; i <= m; i++) {
mp[i] = 0;
}
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
if (a[i] >= 1 && a[i] <= m) {
mp[a[i]]++;
}
}
printf("%d ", per);
cnt = 0;
for (map<int, int>::iterator i = mp.begin(); i != mp.end(); i++) {
if (i->second < per) {
for (int j = 0; j < n; j++) {
if (a[j] > m || a[j] < 1) {
a[j] = i->first;
i->second++;
cnt++;
}
else if (mp[a[j]] > per) {
mp[a[j]]--;
i->second++;
a[j] = i->first;
cnt++;
}
if (i->second >= per) break;
}
}
}
printf("%d\n", cnt);
for (int i = 0; i < n; i++) {
printf(i == 0 ? "%d" : " %d", a[i]);
}
puts("");
return 0;
}