20.Acwing基础课第803题-简单-区间合并

20.Acwing基础课第803题-简单-区间合并

题目描述

给定 n个区间 [li,ri],要求合并所有有交集的区间。

注意如果在端点处相交,也算有交集。

输出合并完成后的区间个数。

例如:[1,3]和[2,6]可以合并为一个区间 [1,6]。

输入格式

第一行包含整数 n。

接下来 n行,每行包含两个整数 l 和 r。

输出格式

共一行,包含一个整数,表示合并区间完成后的区间个数。

数据范围

1≤n≤100000,
−109≤li≤ri≤109

输入样例:

5
1 2
2 4
5 6
7 8
7 9

输出样例:

3

代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 定义成对的整数类型,用来存储区间的左右端点(first=左端点,second=右端点)
typedef pair<int, int> PII;

/**
 * @brief 合并重叠/相邻的区间
 * @param segs 传入存储所有原始区间的vector,合并结果会直接覆盖该vector
 */
void merge(vector<PII> &segs)
{
    // 存储合并后的结果区间
    vector<PII> res;

    // 核心步骤1:按区间左端点从小到大排序(区间合并的前提)
    sort(segs.begin(), segs.end());

    // 初始化当前合并区间的起始(st)和结束(ed),-2e9是极小值(小于题目中可能的区间范围)
    int st = -2e9, ed = -2e9;
    
    // 遍历所有排序后的区间
    for (auto seg : segs)
    {
        // 情况1:当前区间和上一个合并区间无重叠(上一个区间的结束 < 当前区间的开始)
        int l = seg.first, r = seg.second;
        if (ed < l) // 无交集,保存当前区间
        {
            // 如果不是初始的极小值区间(说明已有合并好的区间),加入结果集
            if (st != -2e9) res.push_back({st, ed});
            // 更新当前合并区间为新的未重叠区间
            st = l, ed = r;
        }
        // 情况2:当前区间和上一个合并区间有重叠/相邻,更新合并区间的结束为两者最大值
        else ed = max(ed, seg.second);
    }

    // 处理最后一个合并好的区间(避免遍历结束后遗漏)
    if (st != -2e9) res.push_back({st, ed});

    // 将合并结果覆盖原区间数组
    segs = res;
}

int main()
{
    int n;
    // 读取区间的数量n
    scanf("%d", &n);

    // 存储所有原始区间的数组
    vector<PII> segs;
    for (int i = 0; i < n; i ++ )
    {
        int l, r;
        // 读取每个区间的左右端点
        scanf("%d%d", &l, &r);
        // 将区间加入数组
        segs.push_back({l, r});
    }

    // 调用合并函数处理区间
    merge(segs);

    // 输出合并后的区间数量(核心结果)
    cout << segs.size() << endl;

    return 0;
}
posted @ 2026-03-28 11:08  CodeMagicianT  阅读(2)  评论(0)    收藏  举报