本题要求计算 天安排中,最长的连续无安排(即放假)天数。由于总天数
可能非常大(导致直接用数组标记会内存超限),但安排数量
相对较小,因此我们采用事件点(扫描线)结合差分思想来解决此问题,将复杂度从依赖
降到依赖
。
核心思想:关注变化点
传统的差分数组需要长度为 的数组来记录每一天的状态变化,适用于
较小的情况。当
很大时,我们不再关注每一天,而是只关注状态发生变化的关键时间点。
一个安排 会导致两个关键状态变化:
- 在第
天,状态从“可能放假”变为“有安排”(覆盖数 +1)。
- 在第
天,状态从“有安排”变回“可能放假”(覆盖数 -1)。
通过收集并排序这些关键时间点,我们沿着时间轴进行“扫描”,在两个相邻事件点之间,覆盖状态是恒定的,从而可以计算出这段时间内的放假天数。
算法步骤
1. 收集事件点
我们使用一个 std::map<long long, int> (或 std::vector + 排序) 来存储事件点,其中 key 是时间,value 是状态变化量( 或
)。
- 对于输入的每个安排
:
- 在时间
处记录状态变化
。
- 在时间
处记录状态变化
。
- 在时间
2. 扫描并计算(前缀和)
由于 std::map 会自动根据 key(时间)进行排序,我们只需遍历 map,模拟时间轴上的扫描过程。
-
初始化:
max_happiness = 0(最大快乐值)。current_coverage = 0(当前天数被安排覆盖的次数,即前缀和)。last_time = 1(上一个事件点的时间,初始为第一天)。
-
遍历事件点:
- 设当前事件点时间为
,状态变化为
。
- 计算区间快乐值: 在时间轴上,从
last_time到的这段时间,覆盖状态保持为上一个
current_coverage。- 如果上一个
current_coverage为(即放假状态):
用此天数更新
max_happiness。
- 如果上一个
- 更新状态:
current_coverage += C。 - 更新时间:
last_time = T。
- 设当前事件点时间为
3. 处理末尾区间
遍历结束后,还需要检查从最后一个事件点 last_time 到总天数 结束的这段区间。
-
如果此时
current_coverage仍为且
:
-
如果没有任何安排 (
),
max_happiness应为。
复杂度分析
假设 是总天数,
是安排数量。
| 步骤 | 时间复杂度 | 空间复杂度 | 备注 |
|---|---|---|---|
| 1. 收集事件点 | std::map 或 std::vector 排序所需的时间和空间。 |
||
| 2. 扫描计算 | 遍历 |
||
| 总计 | 算法效率只与安排数量 |
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n;
int m;
cin >> n >> m;
map<long long, int> events;
for (int k = 0; k < m; ++k) {
long long l, r;
cin >> l >> r;
if (l <= n) {
events[l]++;
}
if (r + 1 <= n + 1) {
events[r + 1]--;
}
}
long long max_happiness = 0;
long long current_coverage = 0;
long long last_time = 1;
for (const auto& pair : events) {
long long current_time = pair.first;
int change = pair.second;
if (current_coverage == 0) {
long long holiday_duration = current_time - last_time;
max_happiness = max(max_happiness, holiday_duration);
}
current_coverage += change;
last_time = current_time;
}
if (current_coverage == 0 && last_time <= n) {
long long holiday_duration = n - last_time + 1;
max_happiness = max(max_happiness, holiday_duration);
}
if (events.empty()) {
max_happiness = n;
}
cout << max_happiness << endl;
return 0;
}

京公网安备 11010502036488号