区间合并算法

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


区间合并算法

  • 对于单次的区间合并,可以使用差分算法一次遍历即可,当区间范围在 [ 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;
        }
    }
};

题目链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
区间合并算法可以使用以下方法来实现: 1. 首先,将给定的区间列表按照区间的左端点进行升序排序。这样可以确保相邻的区间在排序后会是连续的。 2. 创建一个新的列表,用于存放合并后的区间。 3. 将排序后的第一个区间加入到新列表中。 4. 遍历排序后的每一个区间,依次与新列表中最后一个区间进行比较。 5. 如果当前区间的左端点大于新列表中最后一个区间的右端点,说明两个区间不重叠,直接将当前区间加入到新列表中。 6. 如果当前区间的左端点小于等于新列表中最后一个区间的右端点,说明两个区间重叠,更新新列表中最后一个区间的右端点为两个区间右端点的较大值。 7. 遍历完所有的区间后,新列表中的区间即为合并后的结果。 以下是使用Python实现的代码: ```python def merge(intervals): intervals.sort(key=lambda x: x <= merged[-1][1]: # 当前区间与新列表中最后一个区间重叠 merged[-1][1 = max(merged[-1][1], interval<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [python 合并区间](https://blog.csdn.net/python_tian/article/details/122197311)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值