题目链接
题意:
有n个数。划分成一些组。要求是每个组内大于等于i的数不超过c[i]个,求划分出最少的组数和构成方案。
思路:
将a[i]数组从大到小排序,再创建一个pair<int,int>的优先队列,first存数组中元素个数,second存数组下标,然后顺序选取a[i](之前已经排过序),如果该数组中元素数小于c[a[i]],那么a[i]就可以放入该数组中,然后将数组元素+1放回队列。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e6+5;
const int inf=0x3f3f3f3f;
int a[N],c[N];
vector<int>v[N];
bool cmp(int a,int b)
{
return a>b;
}
signed main()
{
IOS;
int n,k;
cin>>n>>k;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;//从大到小的优先队列(默认用first排序)
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=1;i<=k;i++)
{
cin>>c[i];
}
sort(a,a+n,cmp);//将a[i]数组从大到小排序
int cnt=0;
q.push(make_pair(0,0));//在优先队列中放入元素(空数组元素)避免报错
for(int i=0;i<n;i++)
{
auto x=q.top();q.pop();//利用优先队列提取出已存在的元素个数最少的数组信息
if(x.first<c[a[i]])
{
v[x.second].push_back(a[i]);//将a[i]放入该数组中
q.push(make_pair(x.first+1,x.second));//将该数组元素个数加一放回优先队列中
}
else
{
cnt++;//开一个新数组
v[cnt].push_back(a[i]);//将a[i]放入新开的数组中
q.push(x);//将原数组放回
q.push(make_pair(1,cnt));//将新数组放入优先队列中
}
}
cout<<cnt+1<<endl;
for(int i=0;i<=cnt;i++)
{
cout<<v[i].size()<<" ";
for(auto j:v[i])
{
cout<<j<<" ";
}
cout<<endl;
}
}