珂朵莉树 老司机树 区间合并

我的问题起源灵佬关于293周赛最后一题的题解

使用范围: 区间合并,当数据量大到差分数组之类的常规解法无能为力的时候

问题描述: H2276

简单来说就是合并区间,并计算区间内数的个数

上题题解的解释:
使用有序字典(SortedDict)存储区间的结束和开始(注意是反的!key是区间的结束,value是区间的开始)。当有新的区间输入时,从头到尾一个个的遍历字典(为了节省时间,一般采用二分直接找到第一个>=传入left的地方再开始遍历),只要有重复的部分就将这个区间合并(其实就是删除这个区间并更新left和right)。

具体题解如下:

class CountIntervals:
    def __init__(self):
        self.d = SortedDict()
        self.cnt = 0  # 所有区间长度和

    def add(self, left: int, right: int) -> None:
        # 遍历所有被 [left,right] 覆盖到的区间(部分覆盖也算)
        # bisect_left(left)返回第一个>=left 的数的索引
        i = self.d.bisect_left(left)
        while i < len(self.d) and self.d.values()[i] <= right:
            r, l = self.d.items()[i]
            left = min(left, l)  # 合并后的新区间,其左端点为所有被覆盖的区间的左端点的最小值
            right = max(right, r)  # 合并后的新区间,其右端点为所有被覆盖的区间的右端点的最大值
            self.cnt -= r - l + 1
            self.d.popitem(i)
        self.cnt += right - left + 1
        self.d[right] = left  # 所有被覆盖到的区间与 [left,right] 合并成一个新区间

    def count(self) -> int:
        return self.cnt

函数套用版本:

from sortedcontainers import SortedDict
all_intervals = SortedDict()
nums_n = 0
def add(interval: list):
    left = interval[0]
    right = interval[1]
    i = all_intervals.bisect_left(left)
    while i < len(all_intervals) and all_intervals.values()[i] <= right:
        r, l = all_intervals.items()[i]
        left = min(l, left)
        right = max(r, right)
        # 这里用了nonlocal记录总的数的个数,在解题时才会有效
        nonlocal nums_n
        nums_n -= r-l+1
        all_intervals.popitem(i)
        # 注意,i并没有更新,这是因为如果上面的操作成功进行,第i个值会被删除,直接用
        #    新的left和right去判断下一和区间,直到进while的条件不满足为止
    nonlocal nums_n
    nums_n += right-left+1
    all_intervals[right] = left
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值