zoukankan      html  css  js  c++  java
  • Codeforces 1342D Multiple Testcases(贪心)

    题目链接

    题目大意

      给(n)个不大于(k)的数,让你尽可能的把它们分成较小的组,每组大于等于(i)的数不超过(c[i])个。

    分析

      从最简单的情况开始考虑,对于(n)个数中最大的数(i),如果数组中一共有(m_i)(i),那么这个数组中大于等于(i)的数的数量就是(m_i)个,所以说将这(m_i)个数分组至少需要(lceil {m_idiv c[i]} ceil)组。如果是(i-1)呢,那么大于等于(i-1)的数的数量就是(m_i+m_{i-1}),需要分的组数至少需要(lceil {(m_i+m_{i-1})div 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;
    }
    
  • 相关阅读:
    Swift
    ios中沙盒
    Mac下安装apk(命令形式)
    iOS 保存异常日志
    android sliding menu
    iOS 苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)
    iOS应用崩溃日志分析
    iOS 推送
    iOS 修改textholder的颜色
    iOS 7.1 UITapGestureRecognizer 不好用的解决办法
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12820121.html
Copyright © 2011-2022 走看看