安吉D8-B
1098 字
5 分钟
安吉D8-B
- 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
原题呈现
B4160 排座位
题目描述
有 个座位,从左到右编号为 .现在有 个小朋友,第 个小朋友可以坐在 这些座位上,每个座位至多坐一个人.
现在请问,如果只保留 这些座位,最多可以给多少小朋友安排座位.请你输出 的所有答案.
例如 , 个小朋友 的区间为 :
- 时:一个可行方案为 ,答案为 ;
- 时:一个可行方案为 ,答案为 ;
- 时:一个可行方案为 ,答案为 ;
输入格式
第一行 个整数 代表座位和小朋友的数量.
接下来 行,每行 个整数 代表第 个小朋友的意愿区间.
输出格式
输出 行,第 行代表只保留前 个座位之后最多可以给几个小朋友安排座位.
输入输出样例 #1
输入 #1
3 32 22 31 3输出 #1
123输入输出样例 #2
输入 #2
8 95 76 75 66 77 75 74 61 17 7输出 #2
11123455数据范围
对于所有数据,.
本题采用捆绑测试,你必须通过子任务中的所有数据点以及其依赖的子任务,才能获得子任务对应的分数.
| 子任务编号 | 分值 | 数据范围 | 特殊性质 | 子任务依赖 |
|---|---|---|---|---|
| 1 | 26 | |||
| 2 | 28 | 1 | ||
| 3 | 11 | |||
| 4 | 26 | 1,2,3 | ||
| 5 | 9 | 1,2,3,4 |
此题使用贪心.
先考虑第 个座位.对于可能坐在这个座位上的小朋友(即左端点 和右端点 满足 ),从这些小朋友中选择最紧急的(即右端点 最小),坐在当前座位中空闲的且在第 个位置上.如果没有小朋友,那么这个位置只能空着,再去往后考虑第 个座位.
每次考虑 个小朋友,需要时间复杂度 ,考虑优化.
由于 时升序枚举的,因此显然,对于一个小朋友 ,如果它曾经成为过“可能坐在这些座位上的小朋友”(设满足该条件的集合为 ),即如果在枚举第 个位置的时刻, 开始满足 ,那么,不会在后面的时刻, 再次开始满足 .即对于每一个 ,最多只会进去 一次,再被删除一次,不会再进去第二次.
因此,可以使用优先队列进行优化.使用一个优先队列记录上述的集合 .将所有小朋友按照左端点排序.在遍历到第 个座位时:
- 将所有满足 且没有进入优先队列的小朋友入队.由于 升序排列,所以,若前一个小朋友没有入队,则后面的小朋友更不可能入队.这里可以使用指针记录.
- 在当前优先队列中,获得 最小的小朋友.若该小朋友的 ,说明该小朋友“过期”了,将该小朋友出队,重新获取一个新的小朋友.
- 如果优先队列为空,则当前位置只能空着.否则,我们就找到了一个可以坐在这个位置上的小朋友.将该小朋友出队,并将答案增加一.
标程
#include <bits/stdc++.h>using namespace std;
const int N = 2e5 + 100;int ans = 0;
struct People { int l, r; friend bool operator<(const People a, const People b) { if (a.l == b.l) return a.r < b.r; return a.l < b.l; }} a[N];
struct People_Prio { int l, r; friend bool operator<(const People_Prio a, const People_Prio b) { return a.r > b.r; }};
int n, m;priority_queue<People_Prio> pq;
signed main() { cin >> n >> m; for (int i = 1; i <= m; i++) { cin >> a[i].l >> a[i].r; } int ptr = 0; sort(a + 1, a + m + 1); for (int i = 1; i <= n; i++) { // 将所有可用的都放入优先队列: while (ptr != m && a[ptr + 1].l <= i) { pq.push({a[++ptr].l, a[ptr].r}); } while (!pq.empty()) { auto top = pq.top(); pq.pop(); if (top.r < i) { continue; } ans++; break; } cout << ans << endl; } return 0;}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


