视频加载失败

安吉D8-B

1098 字
5 分钟
安吉D8-B
原题呈现

B4160 排座位#

题目描述#

nn 个座位,从左到右编号为 1n1 \sim n.现在有 mm 个小朋友,第 ii 个小朋友可以坐在 l[i]r[i]l[i] \sim r[i] 这些座位上,每个座位至多坐一个人.

现在请问,如果只保留 1k1 \sim k 这些座位,最多可以给多少小朋友安排座位.请你输出 k=1nk = 1 \sim n 的所有答案.

例如 n=3,m=3n = 3, m = 333 个小朋友 A,B,CA, B, C 的区间为 [2,2],[2,3],[1,3][2, 2], [2, 3], [1, 3]

  • k=1k = 1 时:一个可行方案为 [C][C],答案为 11
  • k=2k = 2 时:一个可行方案为 [C,B][C, B],答案为 22
  • k=3k = 3 时:一个可行方案为 [C,A,B][C, A, B],答案为 33

输入格式#

第一行 22 个整数 n,mn, m 代表座位和小朋友的数量.

接下来 mm 行,每行 22 个整数 l[i],r[i]l[i], r[i] 代表第 ii 个小朋友的意愿区间.

输出格式#

输出 nn 行,第 kk 行代表只保留前 1k1 \sim k 个座位之后最多可以给几个小朋友安排座位.

输入输出样例 #1#

输入 #1#

3 3
2 2
2 3
1 3

输出 #1#

1
2
3

输入输出样例 #2#

输入 #2#

8 9
5 7
6 7
5 6
6 7
7 7
5 7
4 6
1 1
7 7

输出 #2#

1
1
1
2
3
4
5
5

数据范围#

对于所有数据,1n,m2×105,1l[i]r[i]n1 \leq n, m \leq 2 \times 10^5, 1 \leq l[i] \leq r[i] \leq n

本题采用捆绑测试,你必须通过子任务中的所有数据点以及其依赖的子任务,才能获得子任务对应的分数.

子任务编号分值数据范围特殊性质子任务依赖
126n,m10n, m \leq 10
228n,m100n, m \leq 1001
311n,m5000n, m \leq 5000l[i]=r[i]l[i] = r[i]
426n,m5000n, m \leq 50001,2,3
59n,m2×105n, m \leq 2 \times 10^51,2,3,4

此题使用贪心.

先考虑第 ii 个座位.对于可能坐在这个座位上的小朋友(即左端点 ll 和右端点 rr 满足 lirl\leq i \leq r),从这些小朋友中选择最紧急的(即右端点 rr 最小),坐在当前座位中空闲的且在第 ii 个位置上.如果没有小朋友,那么这个位置只能空着,再去往后考虑第 i+1i+1 个座位.

每次考虑 mm 个小朋友,需要时间复杂度 O(nm)O(nm),考虑优化.

由于 ii 时升序枚举的,因此显然,对于一个小朋友 jj,如果它曾经成为过“可能坐在这些座位上的小朋友”(设满足该条件的集合为 ss),即如果在枚举第 ii 个位置的时刻,jj 开始满足 jsj\in s,那么,不会在后面的时刻,jj 再次开始满足 jsj\in s.即对于每一个 jj,最多只会进去 ss 一次,再被删除一次,不会再进去第二次.

因此,可以使用优先队列进行优化.使用一个优先队列记录上述的集合 ss.将所有小朋友按照左端点排序.在遍历到第 ii 个座位时:

  • 将所有满足 lil \leq i 且没有进入优先队列的小朋友入队.由于 ll 升序排列,所以,若前一个小朋友没有入队,则后面的小朋友更不可能入队.这里可以使用指针记录.
  • 在当前优先队列中,获得 rr 最小的小朋友.若该小朋友的 r<ir<i,说明该小朋友“过期”了,将该小朋友出队,重新获取一个新的小朋友.
  • 如果优先队列为空,则当前位置只能空着.否则,我们就找到了一个可以坐在这个位置上的小朋友.将该小朋友出队,并将答案增加一.

标程

#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;
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

安吉D8-B
https://blog.jerrylab.top/posts/problem/anji2026/D8/B/
作者
Jerry
发布于
2026-08-09
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Jerry
Hello, I'm Jerry.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
最新动态
站点统计
文章
80
分类
3
标签
35
总字数
89,198
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0