Educational Codeforces Round 86 (Rated for Div. 2) 比赛人数15356
[codeforces 1342D] Multiple Testcases 均匀安置
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.com/contest/1342/problem/D
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
D - Multiple Testcases | GNU C++17 | Accepted | 170 ms | 4700 KB |
读懂题意就很困难,反反复复,来来回回,总算弄懂了
However, each testcase should include no more than c1 arrays of size greater than or equal to 1 (≥1), no more than c2 arrays of size greater than or equal to 2, …, no more than ck arrays of size greater than or equal to k. Also, c1≥c2≥⋯≥ck.
上面这句就很难懂。
以样例为例,作说明
Input:
4 3
1 2 2 3
4 1 1
Output:
3
1 2
2 1 3
1 2
Input:
4 3
1 2 2 3
4初始有4个数组,每个数组包含元素个数不能超过3
数组1包含元素个数1
数组2包含元素个数2
数组3包含元素个数2
数组4包含元素个数3
4 1 1
新的数据,包含多组数组,要求如下
包含元素个数大于等于1的数组不能超过4个
包含元素个数大于等于2的数组不能超过1个
包含元素个数大于等于3的数组不能超过1个
Output:
3
输出答案是3,请注意,1+2+1=4,也即初始有4个数组,被分配到多组测试数据中,每个数组只能被分配一次
1 2
包含多组数组:
包含元素个数大于等于1的数组有1个,不能超过4个,符合题意
包含元素个数大于等于2的数组有0个,不能超过1个,符合题意
包含元素个数大于等于3的数组有0个,不能超过1个,符合题意
2 1 3
包含多组数组:
包含元素个数大于等于1的数组有2个,不能超过4个,符合题意
包含元素个数大于等于2的数组有1个,不能超过1个,符合题意
包含元素个数大于等于3的数组有1个,不能超过1个,符合题意
1 2
包含多组数组:
包含元素个数大于等于1的数组有1个,不能超过4个,符合题意
包含元素个数大于等于2的数组有1个,不能超过1个,符合题意
包含元素个数大于等于3的数组有0个,不能超过1个,符合题意
样例模拟如下
4 3
1 2 2 3
4 1 1
位置 3 2 1
当前需要安置数量 1 3 4 安置数量计算见下面说明
当前可安置数量 1 1 4
需要分块数量 1 3 1
故,最少分3组
到达位置3需要安置值3,故安置数量是1
到达位置2需要安置值3,2,2,故安置数量是3
到达位置1需要安置值3,2,2,1,故安置数量是4
安置放在3个数组中
均匀安置过程如下
3安置在数组1
2安置在数组2
2安置在数组3
1安置在数组1
数组1中元素值1 3
数组2中元素值2
数组3中元素值2
AC代码如下
#include <cstdio>
#include <algorithm>
#define maxn 200010
#define LL long long
using namespace std;
int c[maxn],cnt[maxn],ans,head[maxn],tot,len[maxn];
struct node{
int to,next;
}e[maxn];
void add_edge(int u,int v){//邻接表,节省空间
tot++,e[tot].to=v,e[tot].next=head[u],head[u]=tot;
}
int main(){
int n,k,i,j,m,sum=0,b,now=1;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)scanf("%d",&m),cnt[m]++;
for(i=1;i<=k;i++)scanf("%d",&c[i]);
for(i=k;i>=1;i--)sum+=cnt[i],ans=max(ans,(sum-1+c[i])/c[i]);//(sum-1+c[i])/c[i]相当于sum/c[i]向上取整
for(i=k;i>=1;i--)
for(j=1;j<=cnt[i];j++){//处置过程有点向加特林机枪
add_edge(now,i),len[now]++,now++;//均匀放置
if(now>ans)now=1;
}
printf("%d\n",ans);
for(i=1;i<=ans;i++){
printf("%d",len[i]);
for(b=head[i];b;b=e[b].next)printf(" %d",e[b].to);
printf("\n");
}
return 0;
}