Educational Codeforces Round 86 D.Multiple Testcases贪心 + 思维
Posted lasomisolaso~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 86 D.Multiple Testcases贪心 + 思维相关的知识,希望对你有一定的参考价值。
题意:
给出
n
n
n个超过
k
k
k的数,对这
n
n
n个数进行分组。
要求每个组中,大于等于i的数不超过
c
[
i
]
c[i]
c[i]个,
c
[
i
]
c[i]
c[i]是题目给出的数组。
问最少需要分多少组,并给出分组方案。
题解:
- 求最小分组。
首先,我们可以求出至少需要多少组,或者说需要的组数不能比它更小了。我们先不讨论这个组数能不能满足题目要求。
我们可以简单的求出大于
i
i
i的数的个数。对于每一个
i
i
i,设大于等于
i
i
i的数有
g
[
i
]
g[i]
g[i]个。每一个
i
i
i 对组数都会有一个约束条件,组数必须大于等于
⌈
g
i
c
i
⌉
\\lceil \\fracg_ic_i \\rceil
⌈cigi⌉。因为每一组最多
c
[
i
]
c[i]
c[i]个大于等于
i
i
i的数。
遍历
i
i
i,对
⌈
g
i
c
i
⌉
\\lceil \\fracg_ic_i \\rceil
⌈cigi⌉取最大值即是我们需要的最少组数ans。
- 求满足最小分组的分配方案。
接下来我们来分析我们得到的最小组数
a
n
s
ans
ans,是不是最后的答案。也就是这
n
n
n个数能不能在满足题目要求的条件下分配到
a
n
s
ans
ans个组中。
一个分配方案是:首先将
n
n
n个数从小到大排序,然后将这
n
n
n个数依次放入到这
a
n
s
ans
ans个组中。如果一个数放入到第
a
n
s
ans
ans组,那么下一次分配将从第1组开始,直到放完为止。
这种分配方案是可以满足题目要求的,那么
a
n
s
ans
ans就是我们要求的最小分组,
v
e
c
t
o
r
vector
vector也能保存分配方案。
至于方案为什么是满足要求的:
我们可以这样想。
n
n
n个数从小到大排序。按照上面的分配方案, 大于等于m[i]的数被均匀的分配到了
a
n
s
ans
ans组中。而从
a
n
s
ans
ans的求得过程中,我们得知无论i是多少,将大于等于i的数平均分配到
a
n
s
ans
ans组,每组都不会超过
c
[
i
]
c[i]
c[i]个。这样就说明是满足题目要求的了。
代码:
/**
* Author : Xiuchen
* Date : 2020-04-27-23.15.43
* Description : DD.cpp
*/
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<math.h>
#include<iostream>
#include<algorithm>
//#define DEBUG
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 2e5 + 100;
int gcd(int a, int b)
return b ? gcd(b, a % b) : a;
int n, k;
int m[maxn], c[maxn], suf[maxn], cnt[maxn];
vector<int> v[maxn];
int main()
#ifdef DEBUG
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> k;
for(int i = 1; i <= n; i++)
cin >> m[i];
cnt[m[i]]++;
sort(m + 1, m + n + 1);
for(int i = 1; i <= k; i++) cin >> c[i];
for(int i = k; i >= 1; i--) suf[i] = suf[i + 1] + cnt[i];
int ans = 0;
for(int i = 1; i <= k; i++)
int tmp = ceil(1.0 * suf[i] / c[i]);
ans = max(ans, tmp);
int cur = 1;
for(int i = 1; i <= n; i++)
v[cur].push_back(m[i]);
cur++;
if(cur > ans) cur = 1;
cout << ans << endl;
for(int i = 1; i <= ans; i++)
cout << v[i].size() << " ";
for(int j = 0; j < v[i].size(); j++)
cout << v[i][j] << " ";
cout << endl;
return 0;
以上是关于Educational Codeforces Round 86 D.Multiple Testcases贪心 + 思维的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33