CF-Round 86-div2-D题
D. Multiple Testcases
这道题是一道贪心题~
这道题的题目意思我理解了挺久的,实在是有点纠结。
题目大意:现在让你把一个测试样例数组m[]改成多个测试样例数组。给你一个数组c[]:要求改成的多个测试样例数组中每个数组满足大于等于i的数目不超过c[i];(就是这里我原先理解题目意思就是很迷,就是每个数组都需要满足,我原先是这样理解的,然后看测试样例发现怎么不对劲,然后强行又理解为只要多个测试样例中有一个数组满足就行,后来又发现我搞错了测试样例,到最后发现原来是我先开始理解的题目意思。。。)数组c[]的长度是k,那么保证m[]数组中的数据的大小不会超过k。
问分成的测试样例数组的最小数目是多少。
数目你构造出来的数组
本题思路:我们先来解决最小数目的问题。我们可以把m[]数组先从大到小排序。
我们用ans表示分成的最小数目。
当先操作的假设是i,我们可以获得数组m[]中大于等于i的数目有多少,记录下来。这里就是为什么我们把数组m[]从大到小排序的原因,方便计算(当然,你想从小到大排序也是可以的)
我们用while()直接索引到数组m[]中第一个小于i的位置j(数组m[]是从0开始的),所以我们就可以直接获得到大于等于i的数目就是j。
用**(j + c[i] - 1) / c[i]来表示最少的分组数目。其实用ceil(j / c[i])**就行向上取整。c[i]是要求我们的测试样例中大于等于i的不能超过c[i]个。所以获得最小的分组数目就是看看j包含多少个c[i];多出来的需要再开一个数组放进去。
我们这样下来操作完所有的i,我们只需要维护一个最大的ans就行,满足所有的需求嘛~
我们获得到最小的分组数目ans之后,就是分配的环节。
分配的话我们就是平均分配了,构造出来的每个数组每次分一个,这样循环下来分配即可。就可以得到我们的答案了~
代码部分:
#include <bits/stdc++.h>
using namespace std;
int n, k;
int main()
{
scanf ("%d%d", &n, &k);
vector<int> a(n);
vector<int> c(k + 1);
for (int i = 0; i < n; i++)
{
scanf ("%d", &a[i]);
}
for (int i = 0; i < k; i++)
{
scanf ("%d", &c[i + 1]);
}
sort(a.begin(), a.end(), greater<int>());
int ans = 0;
for (int i = k, j = 0; i >= 1; i--)
{
while (j < n && a[j] == i)
{
j++;
}
ans = max(ans, (j + c[i] - 1) / c[i]);
}
vector<vector<int> > res(ans);
for (int i = 0; i < n; i++)
{
res[i % ans].push_back(a[i]);
}
cout << ans << endl;
for (int i = 0; i < ans; i++)
{
int siz = res[i].size();
cout << siz;
for (int j = 0; j < siz; j++)
{
cout << " " << res[i][j];
}
cout << endl;
}
return 0;
}