题意
题意是真难懂,就是给你
n
,
k
(
<
=
2
∗
1
0
5
)
n,k(<=2*10^5)
n,k(<=2∗105),第二行n个数,每个数
<
=
k
<=k
<=k。
然后我们要把n个数分成ans组,每组有一个限制条件,就是k个数,
c
[
i
]
c[i]
c[i]表示每组大于等于
i
i
i的个数要小于等于c[i]个。
c
1
>
=
c
2
>
=
c
3
>
=
.
.
.
>
=
c
k
c_1>=c_2>=c_3>=...>=c_k
c1>=c2>=c3>=...>=ck
求ans最小值。
思路
首先最大的数,肯定限制最大,要么我肯定优先选最大的值,所以先排个序,从最大的数开始选。但是选的这个数分到哪一组,
才能使答案最优呢? 首先我们是从大到小依次选的,所以如果当前这个数往有很多元素的那个组放的话,可能放不下(有限制),
所以当前这个数就放到集合个数最小的那个组里面,如果最小的那个都不满足,就只有重新加入一组,用优先队列维护一下。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
typedef long long ll;
const ll mod = 1e9+7;
int a[man];
int c[man];
struct node{
vector<int>s;
bool operator < (const node &a)const{
return s.size() > a.s.size();
}
};
priority_queue<node>sp;
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
for(int i=1;i<=k;i++){
scanf("%d",c+i);
}
sort(a+1,a+1+n);
node s;
s.s.push_back(a[n]);
sp.push(s);
for(int i=n-1;i>=1;){
node tp = sp.top();
sp.pop();
int num = tp.s.size();
if(c[a[i]]>num){
while(i>=1&&c[a[i]]>num){
tp.s.push_back(a[i]);
num++;
i--;
}
}else{
node s;
num = 0;
while(i>=1&&c[a[i]]>num){
s.s.push_back(a[i]);
num++;
i--;
}
sp.push(s);
}
sp.push(tp);
}
cout << sp.size() << endl;
while(sp.size()){
vector<int> tp = sp.top().s;
sp.pop();
cout << tp.size();
for(int j = 0;j < tp.size();j++){
cout <<" " << tp[j];
}cout << endl;
}
return 0;
}