题解: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

【核心思想】

  1. 问题分析:给定 \(N\) 个互不重叠的预订区间 \([S_i, E_i)\),分布在总可用时间 \([0, T]\) 内。预订未按开始时间排序。求最长连续空闲时间的长度。这是一个排序后扫描问题,关键在于将预订按开始时间排序后,计算相邻预订之间以及边界处的空闲间隔。

  2. 算法选择

    • 排序(Sort):按开始时间 \(S_i\) 升序排列,使得预订按时间轴顺序排列
    • 线性扫描:遍历排序后的预订,计算三段空闲时间:
      • 起始空闲:\([0, a_1.st)\)
      • 中间空闲:\([a_{i-1}.ed, a_i.st)\)(相邻预订之间)
      • 末尾空闲:\([a_n.ed, T]\)
  3. 关键步骤

    • 读入与排序:读入 \(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\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \log N)\),排序 \(O(N \log N)\),扫描 \(O(N)\)
    • 空间复杂度:\(O(N)\),存储预订数组
  5. 排序 + 扫描的核心思想

    • 时序对齐:预订未按时间排序时,无法直接计算相邻间隔。排序后将离散的时间点映射到一维时间轴上
    • 三段覆盖\([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
posted @ 2026-08-06 21:57  团爸讲算法  阅读(12)  评论(0)    收藏  举报