Codeforces 1342D - Multiple Testcases (貪心/后綴和)


WA11到死......


題面

Prob1
Prob2




題意

給定 n 個數 m[i],每個 m[i] 都在 [1,k] 的范圍內

再給定 k 個數 c[i]

要求將所有的 m[i] 進行分組

c[i] 表示每組中大於等於 i 的數不超過 c[i] 個

問最少能分幾組,並輸出分組方案




解題思路

自己的貪心思路錯了,昨晚一個多小時就在WA11上掙扎

直到現在看懂了別人的代碼后……才知道有多奇妙


首先要求出最小分組 q

引入新數組 ar,讓 ar[i] 表示數組 m 中大於等於 i 的數字的個數

又因為 c[i] 數組表示每個分組大於等於 i 的數字的最大個數

所以就能得到,單對於數字 i 而言,最小分組數為 ar[i] 除以 c[i] 向上取整

寫作 ceil(1.0*ar[i]/c[i]) 或者 (ar[i]+c[i]-1)/c[i]

最后,讓答案分組 q 在這些最小分組中取大即可


得出最小分組 q 后

貪心可得,將數組 m 進行排序后

將 m[1], m[2], m[3]... m[n] 循環放入組 T[1], T[2] ... T[q], T[1], T[2] ... 即可得出分組方案

即對於第 i 組 T[i] 而言,它所包含的數為 m[i], m[q+i], m[2q+i], m[3q+i] ...

根據上面對於 q 的解法,能夠保證同一組中的數不會與題意產生沖突


ps. 雖然根據 ar 和 c 數組的定義,m 數組應該是從大到小排序后,從較大的數字開始循環放入的,但實際上從小到大也是可行的




完整程序

(156ms/2000ms)

#include<bits/stdc++.h>
using namespace std;

int m[200050],c[200050],ar[200050];
vector<int> v[200050];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    
    int n,k,i,q=1;
    cin>>n>>k;
    
    for(i=1;i<=n;i++)
    {
        cin>>m[i];
        ar[m[i]]++; //先讓ar數組表示等於i的數字個數
    }
    
    for(i=1;i<=k;i++)
        cin>>c[i];
    
    for(i=k;i;i--)
    {
        ar[i]+=ar[i+1]; //i位置依次加上后面的數量,表示大於等於i的數字個數
        q=max(q,(ar[i]+c[i]-1)/c[i]);
    }
    
    sort(m+1,m+1+n/*,less<int>()*/); //對m數組排序,可選從大到小
    
    for(i=1;i<=n;i++)
        v[i%q].push_back(m[i]); //循環放入vector
    
    cout<<q<<'\n';
    for(i=0;i<q;i++)
    {
        cout<<v[i].size();
        for(int it:v[i])
            cout<<' '<<it;
        cout<<'\n';
    }
    
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM