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]是题目给出的数组。
问最少需要分多少组,并给出分组方案。

题解:

  1. 求最小分组。

首先,我们可以求出至少需要多少组,或者说需要的组数不能比它更小了。我们先不讨论这个组数能不能满足题目要求。
我们可以简单的求出大于 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。

  1. 求满足最小分组的分配方案。

接下来我们来分析我们得到的最小组数 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

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27