「CF1342D Multiple Testcases」
题目大意
给出一个序列,和一些限制,需要将这个序列分到最少的组中使得每个组中大于 \(i\) 的数小于等于 \(c_i\) 个.
分析
先计算最小的组数考虑计算 \(sum_i=\sum_{i=j}^{n}(a_j\geq i)\),计算过程类似一个后缀和,那么就可以直接计算出大于等于 \(i\) 的数至少要放在几组中,然后取max就好了.
然后考虑怎么去放,很显然是按顺序去放(从小到大排序后依次轮流放入)最优,可以保证一定满足,具体证明可以理解一下计算公式.
排序如果用桶排可以做到 \(\mathcal{O}(n+k)\),但是我比较懒,就直接用了 sort.
代码
#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int MAXN=2e5+5;
int n,k;
int arr[MAXN];
int c[MAXN];
int sum[MAXN];
int main()
{
scanf("%d%d",&n,&k);
REP(i,1,n)
{
scanf("%d",&arr[i]);
sum[arr[i]]++;//统计出现次数
}
DOW(i,k-1,1)//后缀和
{
sum[i]+=sum[i+1];
}
int answer=0;
sort(arr+1,arr+1+n);
REP(i,1,k)
{
scanf("%d",&c[i]);
}
REP(i,1,k)
{
answer=max(answer,sum[i]/c[i]+(bool)(sum[i]%c[i]));//计算最小组数
}
printf("%d\n",answer);
REP(i,1,answer)
{
int now=i,p=0;
while(now<=n)//考虑是按组数循环,先计算出个数再输出
{
++p;
now+=answer;
}
printf("%d ",p);
now=i;
while(now<=n)
{
printf("%d ",arr[now]);
now+=answer;
}
printf("\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!