【ACWing 算法基础】区间合并

一. 模板

// 将所有存在交集的区间合并
void merge(vector<PII> &segs)
{
    vector<PII> res;

    sort(segs.begin(), segs.end());  // 按左端点排序

    int st = -2e9, ed = -2e9;  // ed代表区间结尾,st代表区间开头
    for (auto seg : segs)
        if (ed < seg.first)  // 情况1:两个区间无法合并
        {
            if (st != -2e9) res.push_back({st, ed});  // 区间1放进res数组
            st = seg.first, ed = seg.second;  // 维护区间2
        }
        else ed = max(ed, seg.second);  // 情况2,3:能够合并,新区间右端点和远区间右端点谁大更新为谁   
        //注:排过序之后,不可能有区间2包含区间1

    if (st != -2e9) res.push_back({st, ed});  // 放入最后一个区间,防止空数据
    
    segs = res;
}

二. 总结

  • 精髓就是:按左端点排序,然后再模拟可能的情况
  • 排序后可能的三种情况:
    【ACWing 算法基础】区间合并_第1张图片

三. 例题

  • 803. 区间合并
    【ACWing 算法基础】区间合并_第2张图片

AC代码:

#include 
#include 
#include 

using namespace std;

typedef pair<int, int> PII;

vector<PII> segs;

// 合并区间
void merge(vector<PII> &segs)
{
    // 按左端点排序
    sort(segs.begin(), segs.end());
    
    int st = -2e9, ed = -2e9;  // st 为区间左端点,ed 为区间右端点
    vector<PII> res;   
    for (auto seg : segs) {
        if (ed < seg.first) {  // 情况1:不能合并
            if (st != -2e9) res.push_back({seg.first, seg.second});
            st = seg.first, ed = seg.second;  // 更新比较的区间
        }
        else ed = max(ed, seg.second);  // 情况2,3:能够合并,新区间右端点和远区间右端点谁大更新为谁                                   // 不存在原区间在新区间中间的情况-> 以左端点排序保证
    }
    
    if (st != -2e9) res.push_back({st, ed});  // 放入最后一个区间,防止空数据
    
    segs = res;
}

int main()
{   
    int n;
    cin >> n;
    
    int l, r;
    for (int i = 0; i < n; ++i) {
        cin >> l >> r;
        segs.push_back({l, r});
    }
    
    merge(segs);
    
    cout << segs.size() << endl;
}

你可能感兴趣的:(数据结构与算法,算法,c++,数据结构)