Codeforces 1342D Multiple Testcases(贪心)
Posted shuitiangong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1342D Multiple Testcases(贪心)相关的知识,希望对你有一定的参考价值。
题目大意
??给(n)个不大于(k)的数,让你尽可能的把它们分成较小的组,每组大于等于(i)的数不超过(c[i])个。
分析
??从最简单的情况开始考虑,对于(n)个数中最大的数(i),如果数组中一共有(m_i)个(i),那么这个数组中大于等于(i)的数的数量就是(m_i)个,所以说将这(m_i)个数分组至少需要(lceil {m_i/c[i]} ceil)组。如果是(i-1)呢,那么大于等于(i-1)的数的数量就是(m_i+m_{i-1}),需要分的组数至少需要(lceil {(m_i+m_{i-1})/c[i-1]} ceil)组。等等,是不是忘了什么?我们前面分的组数和后面不一定是相等的,所以要想满足每个条件,肯定要取最大的组数。我们知道了组数了具体该怎么分呢?经过前面的计算我们已经得到了最小可行的组数,所以我们只要按顺序把各个数均摊到我们分的组里就行了。
具体实现
??我们可以先用一个桶来计数,算出每个数字出现的次数,然后倒着求后缀和,就能得到大于当前数字的数量,后面求最大分组就很容易了(记得向上取整)。后面的分组可以用模运算。
代码
const int maxn = 2e5+10;
vector<int> ans[maxn];
int cnt[maxn], c[maxn];
int main(void) {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0, num; i<n; ++i) {
scanf("%d", &num);
++cnt[num];
}
for (int i = 1; i<=k; ++i) scanf("%d", &c[i]);
int sum = 0, maxx = -1;
for (int i = k; i>=1; --i) {
sum += cnt[i+1];
//cout << sum << endl;
maxx = max(maxx, (sum+c[i]-1)/c[i]);
}
int tot = 0;
for (int i = k; i>=1; --i)
while(cnt[i]) {
ans[tot%maxx].push_back(i);
--cnt[i];
++tot;
}
printf("%d
", maxx);
for (int i = 0; i<maxx; ++i)
if (!ans[i].empty()) {
printf("%d", (int)ans[i].size());
for (auto num : ans[i]) printf(" %d", num);
putchar(endl);
}
return 0;
}
以上是关于Codeforces 1342D Multiple Testcases(贪心)的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 86 (Rated for Div. 2) D. Multiple Testcases