【算法】区间合并

0 阅读2分钟

题目:

image.png

思路:

  1. 按左端点排序

  2. 再维护一个区间,与后面一个个区间进行三种情况的比较,存储到数组里去。

image.png

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef pair<int,int> PII;  
// 存储一对 int 类型的数值 `PII seg = {1, 3}` 表示一个从 1 到 3 的区间

void merge(vector<PII> &segs)  
{
    vector<PII> res;  // 存储合并区间之后的数据对
    sort(segs.begin(),segs.end()); // C++对pair容器排序规则是按照第一个数据排序 即先按左端点排序

    int st = -2e9,ed = -2e9;  
    // 初始无效值 st和ed分别作为维护(被比较)区间左右端点,seg.first,seg.second分别作为当前区间左右端点

    for(auto seg:segs)  // 遍历segs中每一个元素
    {
        if(ed<seg.first) // 若维护区间和当前区间没有交集(维护区间右端点在当前区间左端点的左边)
        {
            if(st != -2e9) res.push_back({st,ed}); 
            // 1.此时若维护区间不是初始定义区间,说明维护区间可作为独立区间加入到res
            // 把当前区间更新为维护区间,下一个区间与它做端值的比较
            st = seg.first,ed = seg.second;             
        }
        else ed = max(ed,seg.second);                
        // 2.不管是维护区间包含当前区间还是维护区间和当前区间有交集,
        // 都把维护区间右端点更新为维护区间和当前区间右端点中更大的那一个
    }
    
    if(st != -2e9) res.push_back({st,ed});   
      // 在for循环结束中最后一个区间只是更新成了维护区间,并没有把它加入到res中,现在把它也放进来
      
    segs=res; // 把合并后的结果赋值给原vector                          
}

int main()
{
    int 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);
    printf("%d",segs.size());
    return 0;
}