Educational Codeforces Round 86 (Rated for Div. 2)-D. Multiple Testcases(优先队列,贪心)

题目链接

题意:

有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;
    }
}

猜你喜欢

转载自blog.csdn.net/ACkingdom/article/details/106267237