WA11到死......
題面


題意
給定 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;
}
