Educational Codeforces Round 86 D.Multiple Testcases【贪心 + 思维】

题目链接
在这里插入图片描述

题意:

给出 n n 个超过 k k 的数,对这 n n 个数进行分组。
要求每个组中,大于等于i的数不超过 c [ i ] c[i] 个, c [ i ] c[i] 是题目给出的数组。
问最少需要分多少组,并给出分组方案。

题解:

  1. 求最小分组。

首先,我们可以求出至少需要多少组,或者说需要的组数不能比它更小了。我们先不讨论这个组数能不能满足题目要求。
我们可以简单的求出大于 i i 的数的个数。对于每一个 i i ,设大于等于 i i 的数有 g [ i ] g[i] 个。每一个 i i 对组数都会有一个约束条件,组数必须大于等于 g i c i \lceil \frac{g_i}{c_i} \rceil 。因为每一组最多 c [ i ] c[i] 个大于等于 i i 的数。
遍历 i i ,对 g i c i \lceil \frac{g_i}{c_i} \rceil 取最大值即是我们需要的最少组数ans。

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

接下来我们来分析我们得到的最小组数 a n s ans ,是不是最后的答案。也就是这 n n 个数能不能在满足题目要求的条件下分配到 a n s ans 个组中。
一个分配方案是:首先将 n n 个数从小到大排序,然后将这 n n 个数依次放入到这 a n s ans 个组中。如果一个数放入到第 a n s ans 组,那么下一次分配将从第1组开始,直到放完为止。
这种分配方案是可以满足题目要求的,那么 a n s ans 就是我们要求的最小分组, v e c t o r vector 也能保存分配方案。
至于方案为什么是满足要求的:
我们可以这样想。 n n 个数从小到大排序。按照上面的分配方案, 大于等于m[i]的数被均匀的分配到了 a n s ans 组中。而从 a n s ans 的求得过程中,我们得知无论i是多少,将大于等于i的数平均分配到 a n s ans 组,每组都不会超过 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;
}

猜你喜欢

转载自blog.csdn.net/qq_44607936/article/details/105827638