区间合并算法

前言: 最近都在忙毕设和论文,已经好久没有写博客了。今天打周赛的时候遇到了区间合并的问题,前来记录一下。


区间合并算法

  • 对于单次的区间合并,可以使用差分算法一次遍历即可,当区间范围在 [ 0 , 1 0 18 ] [0, 10^{18}] [0,1018] 的时间复杂度为 n l o g n nlogn nlogn
  • 但是对于多区间问题,使用上述算法肯定会超时,因此这里来介绍一个 n l o g n nlogn nlogn 的区间合并与修改的算法模板。
/***
    * @author : Laugh
    * 适用范围 : 
    * 1. 用于管理形式为 [l, r) 的整数区间,区间无重叠
    * 2. 加入 multiset<int> 可以实现 O(1) 获取最大长度 
    * 3. all 属性为所有区间的长度之和
    * 
*/

class RangeModule { 
public:    
    int all;
    // 不相交区间集合,存储形式为 [r, l)
    set<pair<int, int>> rec;

    RangeModule() {
        all = 0;
    }
    
    // 插入区间 [L, R)
    void insert(int L, int R) {   
        auto pos = rec.lower_bound({L, 0});
        while(pos != rec.end()){
            auto [r, l] = *pos;
            if(l > R)
                break;
            all -= r - l;
            L = min(L, l);
            R = max(R, r);
            rec.erase(pos++);
        }
        rec.emplace(R, L);
        all += R - L;
    }
    
    // 判断是否包含某个区间
    bool query(int L, int R) {
        auto pos = rec.lower_bound({R, 0});
        return pos != rec.end() and pos->second <= L;
    }
    
    // 删除区间 [L, R)
    void remove(int L, int R) {
        auto pos = rec.lower_bound({L + 1, 0});
        vector<pair<int, int>> rest;

        while(pos != rec.end()){
            auto [r, l] = *pos;
            if(l >= R)
                break;
            all -= r - l;

            // 若不完全包含最左和最右区间,需要修改后插入
            if(l + 1 <= L)
                rest.emplace_back(L, l);
            if(R < r)
                rest.emplace_back(r, R);
            rec.erase(pos++);
        }
        
        for(auto &[r, l] : rest){
            rec.emplace(r, l);
            all += r - l;
        }
    }
};

题目链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值