题解:AtCoder AT_awc0129_b Available Time Slots for Meeting Rooms
【题目来源】
AtCoder:B - Available Time Slots for Meeting Rooms
【题目描述】
Takahashi is in charge of managing meeting room reservations at his company.
The meeting room is available during the interval \([0, T]\), from time \(0\) to time \(T\).
There are \(N\) reservations for the meeting room today. The \(i\)-th reservation starts at time \(S_i\) and ends at time \(E_i\). That is, the \(i\)-th reservation occupies the half-open interval \([S_i, E_i)\). The time intervals of the reservations do not overlap with each other. However, the reservations are not necessarily given in ascending order of start time.
Among the available time \([0, T]\), the portions not used by any reservation are called free time. Takahashi wants to secure the longest possible continuous free time for a meeting that was suddenly scheduled.
Find the length of the longest continuous free time in today's meeting room. If there is no free time, output \(0\).
高橋负责管理公司的会议室预订。
会议室在时间段 \([0, T]\) 内可用,即从时刻 \(0\) 到时刻 \(T\)。
今天有 \(N\) 个会议室预订。第 \(i\) 个预订从时刻 \(S_i\) 开始,到时刻 \(E_i\) 结束。也就是说,第 \(i\) 个预订占用左闭右开区间 \([S_i, E_i)\)。各个预订的时间段互不重叠。但是,预订不一定按开始时间的升序给出。
在可用时间 \([0, T]\) 中,未被任何预订使用的部分称为空闲时间。高橋想为突然安排的一场会议争取尽可能长的连续空闲时间。
求今天会议室中最长连续空闲时间的长度。如果没有空闲时间,输出 \(0\)。
【输入】
\(N\) \(T\)
\(S_1\) \(E_1\)
\(S_2\) \(E_2\)
\(\vdots\)
\(S_N\) \(E_N\)
- The first line contains an integer \(N\) representing the number of reservations and an integer \(T\) representing the end of the meeting room's available time, separated by a space.
- From the 2nd line to the \((N + 1)\)-th line, the start time and end time of each reservation are given.
- The \((1 + i)\)-th line contains the start time \(S_i\) and end time \(E_i\) of the \(i\)-th reservation, separated by a space.
【输出】
Output the length of the longest continuous free time in a single line. If there is no free time, output \(0\).
【输入样例】
3 10
1 3
5 6
8 9
【输出样例】
2
【核心思想】
-
问题分析:给定 \(N\) 个互不重叠的预订区间 \([S_i, E_i)\),分布在总可用时间 \([0, T]\) 内。预订未按开始时间排序。求最长连续空闲时间的长度。这是一个排序后扫描问题,关键在于将预订按开始时间排序后,计算相邻预订之间以及边界处的空闲间隔。
-
算法选择:
- 排序(Sort):按开始时间 \(S_i\) 升序排列,使得预订按时间轴顺序排列
- 线性扫描:遍历排序后的预订,计算三段空闲时间:
- 起始空闲:\([0, a_1.st)\)
- 中间空闲:\([a_{i-1}.ed, a_i.st)\)(相邻预订之间)
- 末尾空闲:\([a_n.ed, T]\)
-
关键步骤:
- 读入与排序:读入 \(N, T\) 和 \(N\) 个预订,按
st升序排序 - 计算空闲时间:
ans = max(ans, a[1].st - 0):\(0\) 到第一个预订开始前的空闲- 遍历 \(i\) 从 \(2\) 到 \(N\):
ans = max(ans, a[i].st - a[i-1].ed):第 \(i-1\) 个预订结束到第 \(i\) 个预订开始前的空闲 ans = max(ans, T - a[n].ed):最后一个预订结束到 \(T\) 的空闲
- 输出 \(ans\)
- 读入与排序:读入 \(N, T\) 和 \(N\) 个预订,按
-
时间/空间复杂度:
- 时间复杂度:\(O(N \log N)\),排序 \(O(N \log N)\),扫描 \(O(N)\)
- 空间复杂度:\(O(N)\),存储预订数组
-
排序 + 扫描的核心思想:
- 时序对齐:预订未按时间排序时,无法直接计算相邻间隔。排序后将离散的时间点映射到一维时间轴上
- 三段覆盖:\([0, T]\) 被 \(N\) 个预订分割为 \(N+1\) 个潜在空闲段(含边界),只需检查这些段
- 互不重叠的简化:题目保证预订不重叠,无需处理区间相交的复杂情况,直接相减即可得空闲长度
- 适用于"在有序区间序列中寻找最大间隔"的问题,核心在于排序创造单调性,将二维区间问题转化为一维扫描
【算法标签】
贪心
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 200005; // 定义数组最大容量为200005
int n, t, ans = -1e9; // n为预订数量,t为会议室可用时间终点,ans记录最长连续空闲时间(初始化为极小值)
struct Node
{
int st, ed; // st为预订开始时间,ed为预订结束时间
} a[N]; // a数组存储n个预订的信息
// 自定义排序规则:按开始时间升序排列
bool cmp(Node x, Node y)
{
return x.st < y.st; // 按开始时间从小到大排序
}
int main()
{
cin >> n >> t; // 读入预订数量n和会议室可用时间终点t
for (int i = 1; i <= n; i++) // 读入每个预订的开始和结束时间
cin >> a[i].st >> a[i].ed;
sort(a + 1, a + n + 1, cmp); // 按开始时间升序排序所有预订
// 计算第一段空闲时间:从时刻0到第一个预订的开始时间
ans = max(ans, a[1].st - 0);
// 计算中间各段空闲时间:相邻两个预订之间的间隔
for (int i = 2; i <= n; i++)
ans = max(ans, a[i].st - a[i - 1].ed); // 当前预订开始时间 - 上一个预订结束时间
// 计算最后一段空闲时间:从最后一个预订的结束时间到时刻t
ans = max(ans, t - a[n].ed);
// 如果没有空闲时间(所有预订恰好覆盖[0,T]),ans可能为0或负数,需要与0取max
// 但题目中预订互不重叠且都在[0,T]内,ans至少为0(当预订覆盖整个区间时各段空闲为0)
cout << ans << endl; // 输出最长连续空闲时间的长度
return 0;
}
【运行结果】
3 10
1 3
5 6
8 9
2
浙公网安备 33010602011771号