洛谷 - P1496 火烧赤壁

题目链接

考察知识点

  • 算法 - 模拟

思路分析

考虑用模拟的方法解决这道题。

先把读入的线段按照左端小在前的原则进行排序,显然这样排序产生的答案必定正确。

对所有线段进行区间合并,统计合并后的每个线段长度之和。

注意:数据中的线段左闭右开

时间复杂度

\(O(n)\)

C++代码

// Problem: P1496 火烧赤壁
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1496
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <cstdio>       // 包含标准输入输出函数库
#include <algorithm>    // 包含排序等算法函数库
#include <vector>       // 包含向量容器类库
using namespace std;    // 引入标准命名空间

// 定义一个别名PII,表示成对的整数(用于存储区间的起点和终点)
typedef pair<int, int> PII;
// 定义一个向量容器segs,用于存储所有的着火区间信息
vector<PII> segs;
// 定义整数n,用于存储着火信息的条数
int n;


//合并重叠或相邻的区间
void merge(vector<PII> &segs) {
    // 先将所有区间按照起点从小到大排序
    sort(segs.begin(), segs.end());
    
    // 定义一个临时向量res,用于存储合并后的区间
    vector<PII> res;
    // 初始化当前区间的起点st和终点ed(使用一个极小值作为初始值)
    int st = -2e9, ed = -2e9;
    
    // 遍历每一个区间
    for (auto seg : segs) {
        // 取出当前区间的起点l和终点r
        int l = seg.first, r = seg.second;
        
        // 如果当前区间的起点大于上一个区间的终点,说明两个区间不重叠
        if (ed < l) {
            // 如果不是初始区间(避免添加默认的极小值区间),则将上一个区间加入结果
            if (st != -2e9) res.push_back({st, ed});
            // 更新当前区间为新的区间
            st = l, ed = r;
        } else {
            // 如果区间重叠或相邻,则合并区间(更新终点为两个区间终点的最大值)
            ed = max(ed, r);
        }
    }
    
    // 循环结束后,将最后一个区间加入结果(避免遗漏)
    if (st != -2e9) res.push_back({st, ed});
    // 将合并后的结果赋值给原向量
    segs = res;
}

int main() {
    // 读取着火信息的条数n
    scanf("%d", &n);
    
    // 循环读取n条着火区间信息
    for (int i = 1; i <= n; i++) {
        int l, r;
        // 读取区间的起点l和终点r(题目中是左闭右开区间)
        scanf("%d%d", &l, &r);
        // 将左闭右开区间转换为左闭右闭区间(方便计算长度),并加入到segs中
        // 原区间[a, b)等价于[a, b-1](闭区间)
        segs.push_back({l, r - 1});
    }
    
    // 调用merge函数合并重叠的区间
    merge(segs);
    
    // 定义变量ans,用于存储最终的燃烧总长度
    int ans = 0;
    // 遍历合并后的所有区间,计算总长度
    for (auto seg : segs) {
        // 对于左闭右闭区间[st, ed],长度为ed - st + 1
        ans += seg.second + 1 - seg.first;
    }
    
    // 输出计算得到的总长度
    printf("%d\n", ans);
    
    return 0;
}
posted @ 2025-08-19 23:04  九三青梧  阅读(21)  评论(0)    收藏  举报