安吉D9-T2
1101 字
6 分钟
安吉D9-T2
- 1安吉D19 T1
- 2安吉D19 T3
- 3安吉D20 模考12总结
- 4安吉D17 T3
- 5安吉D17 T4
- 6安吉D19 模考11总结
- 7安吉D15 A
- 8安吉D16 T4
- 9安吉D17 T1
- 10安吉D17 模考10总结
- 11安吉D16 T3
- 12安吉D16 模考9总结
- 13安吉D13 模考8总结
- 14安吉D13-T2
- 15安吉D13-T3
- 16安吉D12-T3
- 17安吉D11-B
- 18安吉D11-C
- 19安吉D11-D
- 20安吉D12 模考7总结
- 21安吉D12-T2
- 22安吉D11-A
- 23安吉D10 模考6总结
- 24安吉D10-T3
- 25安吉D10-T4
- 26安吉D8-E
- 27安吉D9-T4
- 28安吉D8-A
- 29安吉D8-B
- 30安吉D8-C
- 31安吉D8-D
- 32安吉D9 模考5总结
- 33安吉D9-T2本文
- 34安吉D9-T3
- 35安吉D6-T4
- 36安吉D4-G
- 37安吉D5-T2
- 38安吉D6 模考4总结
- 39安吉D6-T1
- 40安吉D6-T3
- 41安吉-开营测试 T4
- 42安吉D5 模考3总结
- 43安吉D5-T3
- 44安吉D4-A
- 45安吉D4-B
- 46安吉D4-C
- 47安吉D4:容斥原理
- 48安吉Day4-D
- 49安吉D3 模考2总结
- 50安吉D3-T1
- 51安吉D3-T2
- 52安吉D3-T4
- 53安吉D2 模考1总结
- 54安吉D2-T2
- 55安吉D1-G
- 56安吉D1-L
- 57安吉D2-T4
原题呈现
P4447 分组
题目描述
小可可的学校信息组总共有 个队员,每个人都有一个实力值 .现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的 个队员分成若干个小组去参加这场比赛.
但是每个队员都不会愿意与实力跟自己过于悬殊的队员组队,于是要求分成的每个小组的队员实力值连续,同时,一个队不需要两个实力相同的选手.举个例子: 是合法的分组方案,因为实力值连续; 不是合法的分组方案,因为实力值不连续; 同样不是合法的分组方案,因为出现了两个实力值为 的选手.
如果有小组内人数太少,就会因为时间不够而无法获得高分,于是小可可想让你给出一个合法的分组方案,满足所有人都恰好分到一个小组,使得人数最少的组人数最多,输出人数最少的组人数的最大值.
注意:实力值可能是负数,分组的数量没有限制.
输入格式
输入有两行:
第一行一个正整数 ,表示队员数量.
第二行有 个整数,第 个整数 表示第 个队员的实力.
输出格式
输出一行,包括一个正整数,表示人数最少的组的人数最大值.
输入输出样例 #1
输入 #1
74 5 2 3 -4 -3 -5输出 #1
3说明/提示
样例解释
分为 组,一组的队员实力值是 ,一组是 ,其中最小的组人数为 ,可以发现没有比 更优的分法了.
数据范围
对于 的数据满足:,.
本题共 个测试点,编号为 ,每个测试点额外保证如下:
| 测试点编号 | 数据限制 |
|---|---|
| 且 互不相同 | |
| , 互不相同 | |
此题使用贪心.
考虑下面这个情景:有一些人已经分好了组,每一组可以看作一条链,每一条链都单调递增,且公差为 1.现在,来了一个实力值正好同时可以接在这几条链末尾的人.此时,不难发现贪心策略:将这个人放在最短的链末尾.
依照这个策略,我们可以建立一个优先队列,用于存储以当前值减一为末尾的链的长度.在读取输入时,记录每个权值和对应的人数,接下来,从小到大遍历每一个权值 :
- 对于每一个权值为 的人:可以接在当前处于优先队列中的最短的链上.更新长度,并将长度移动到第二个优先队列(该队列用于保存已经吸纳了当前权值的人的小组,即以当前值为末尾的链).
- 在遍历完该权值的所有人之后,如果有一组没有收集到该权值的任意一个人(即还留在第一个优先队列),那么该链断裂,不能再吸纳更多的人.将其与答案取最小值,并删除这一条链.
- 将所有存于第二个优先队列的链移动到第一个.
标程:
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 100;int n, a[N], ans = 1e9 + 10;priority_queue<int> us[2];
struct Node { int v, num; friend bool operator<(const Node a, const Node b) { return a.v < b.v; }} d[N];
void clear(int idx) { while (!us[idx].empty()) { ans = min(ans, -us[idx].top()); us[idx].pop(); }}
signed main() { cin >> n; int cnt = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + n + 1); for (int i = 1; i <= n; i++) { if (a[i] == a[i - 1]) { d[cnt].num++; } else { d[++cnt].v = a[i]; d[cnt].num = 1; } } for (int i = 1; i <= cnt; i++) { int now = i & 1, pre = (i - 1) & 1; if (d[i].v != d[i - 1].v + 1) { clear(pre); } for (int j = 1; j <= d[i].num; j++) { if (us[pre].empty()) { us[now].push(-1); } else { int top = us[pre].top(); us[pre].pop(); us[now].push(top - 1); } } clear(pre); } clear(0); clear(1); cout << ans; return 0;}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


