Showering 的题解
记住只在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。
在解题之前提交题解的代码会导致封禁。
在解题之前提交题解的代码会导致封禁。
作者:
概述
本题给定一天内不重叠的若干任务区间,要求判断是否存在长度至少为 的连续空闲时间段。核心解法是检查相邻任务之间的间隔、起始空闲段和末尾空闲段,取其中最大值与
比较。
分析
核心观察
任务区间互不重叠且按顺序给出(输入保证 ),因此只需检查任务区间之间的空隙以及一天开头和结尾的空闲时间。
思路
设一天从时刻 开始到时刻
结束。给定
个任务区间
,其中
。由于区间不重叠且有序,可能的空闲段包括:
- 从
到第一个任务开始前的空闲段,长度为
。
- 第
个任务结束后到第
个任务开始前的空闲段,长度为
,其中
。
- 最后一个任务结束后到
的空闲段,长度为
。
若上述任一长度大于等于 ,则 Alex 可以洗澡;否则不能。本题只需判断存在性,不必输出具体方案。
具体示例
以样例第一组 ,任务为
:起始空闲
,满足
,输出
YES。
第二组任务 :起始空闲
,中间间隔
,
,末尾空闲
,输出
YES。
第三组任务 :末尾空闲
,所有间隔均小于
,输出
NO。
算法步骤
- 对每个测试用例,读入
。
- 初始化上一个任务结束时间
prev_r = 0(表示一天开始时刻)。
- 设置标志
can = false。 - 循环读取
个任务区间:
- 读入当前任务的
。
- 检查当前空闲段长度
l_i - prev_r是否大于等于,若是则置
can = true。 - 更新
prev_r = r_i。
- 读入当前任务的
- 循环结束后,检查末尾空闲段长度
m - prev_r是否大于等于,若是则置
can = true。 - 若
can为真输出YES,否则输出NO。
复杂度分析
- 时间:每个测试用例
,所有测试用例的
之和不超过
。
- 空间:
额外空间(不计输入缓存)。
实现注意事项
- 任务区间保证有序且不重叠,无需排序。
- 使用 64 位整数(
long long)存储时间值,因为可到
,但
之和为
,加法仍在
int范围内,但为安全可用long long。 - 注意起始空闲段已包含在循环之前的检查中(可将
prev_r初始化为,循环内检查第一个任务前空闲)。
- 末尾空闲段在循环结束后单独检查。
源代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
long long s, m;
cin >> n >> s >> m;
long long prev_r = 0;
bool ok = false;
for (int i = 0; i < n; ++i) {
long long l, r;
cin >> l >> r;
if (l - prev_r >= s) ok = true;
prev_r = r;
}
if (m - prev_r >= s) ok = true;
cout << (ok ? "YES" : "NO") << '\n';
}
return 0;
}
import sys
def solve():
data = sys.stdin.read().strip().split()
if not data:
return
idx = 0
t = int(data[idx]); idx += 1
out = []
for _ in range(t):
n = int(data[idx]); s = int(data[idx+1]); m = int(data[idx+2]); idx += 3
prev_r = 0
ok = False
for _ in range(n):
l = int(data[idx]); r = int(data[idx+1]); idx += 2
if l - prev_r >= s:
ok = True
prev_r = r
if m - prev_r >= s:
ok = True
out.append("YES" if ok else "NO")
sys.stdout.write("\n".join(out))
if __name__ == "__main__":
solve()
评论