题目链接
题意:给你一个初始数组,要你把他分类,每一类集合中的ai大于等于1的个数要不超过c1,大于等于2的个数要不超过c2,以此类推,要你输出最少的分类组数
思路:我们先从大到小排序,然后对于每个ai我们考虑把它放进那个桶比较合适,由于要最小化桶的数量,我们肯定是能放进第一个桶就尽量放,不行就第二个,以此类推,这个过程可以二分优化,就是如果一个桶的大小+1小于等于ai的限制的话就说明能放进这个桶,因为我们从大到小排序后再放桶的,所以每个桶里的每个数都是递增的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int sum=0,n,k,a[maxn],c[maxn],num[maxn];
vector<int>ans[maxn],v;
int check(int left,int right,int k)
{
int l=left,r=right;
while(l<=r)
{
int mid=(l+r)>>1;
if(num[mid]+1<=k) r=mid-1;
else l=mid+1;
}
return l;
}
int main()
{
scanf("%d %d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
for(int i=1;i<=k;++i) scanf("%d",&c[i]);
for(int i=n;i>=1;--i)
{
int pos=check(1,n,c[a[i]]);
ans[pos].push_back(a[i]),num[pos]++;
}
for(int i=1;i<=n;++i) if(ans[i].size()>0) sum++;
printf("%d\n",sum);
for(int i=1;i<=n;++i)
{
if(ans[i].size()==0) continue;
printf("%d ",ans[i].size());
for(int j:ans[i]) printf("%d ",j);
puts("");
}
}