要维护区间集合,区间按起点排

插入新区间

vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
    // 区间互不重叠、已按起点排序
    vector<vector<int>> before, after; // 前后的不重叠区间
    int left = newInterval[0], right = newInterval[1];
    for (auto& interval : intervals) {
        if (interval[1] < left) before.push_back(interval);
        else if (interval[0] > right) after.push_back(interval);
        else {
            left = min(left, interval[0]);
            right = max(right, interval[1]);
        }
    }

    before.push_back({left, right});
    before.insert(end(before), begin(after), end(after));
    return before;
}

合并区间列表

vector<vector<int>> merge(vector<vector<int>>& intervals) {
    if (intervals.empty()) return {};
    sort(begin(intervals), end(intervals));
    
    vector<vector<int>> ans;
    for (auto &interval : intervals) {
        if (ans.empty() || interval[0] > ans.back()[1]) {
            ans.push_back(interval);
        } else {
            ans.back()[1] = max(ans.back()[1], interval[1]);
        }
    }
    return ans;
}
区间数组合并后的总长
int getWidth(multiset<vector<int>> &st) {
    int ans = 0;
    int curr = INT_MIN;
    // curr往右扩展,只累加变长的部分
    for (auto &x : st) {
        curr = max(curr, x[0]);
        ans += max(x[1] - curr, 0);
        curr = max(curr, x[1]);
    }
    return ans;
}

或者同上题写法


维护区间集合

class RangeModule {
    map<int, int> _ranges; // left=>right, [left,right)
    using RI = map<int, int>::iterator;
    array<RI, 2> getOverlapRanges(int left, int right) {
        // 在端点重合处,认为重叠
        // 左边找第一个相交的区间
        auto l = _ranges.upper_bound(left); // toFind.left>left
        if (l != begin(_ranges) && prev(l)->second >= left) // toFind.left<=left&&toFind.right>=left
            l = prev(l);
        // 右边找第一个不相交的区间
        auto r = _ranges.upper_bound(right); // toFind.left>right
        return {l, r};
    }
public:
    RangeModule() { 
    }
    
    void addRange(int left, int right) {
        auto [l, r] = getOverlapRanges(left, right);
        if (l != r) {
            left = min(left, l->first);
            right = max(right, prev(r)->second);
            _ranges.erase(l, r);
        }
        _ranges[left] = right;
    }
    
    bool queryRange(int left, int right) {
        auto [l, r] = getOverlapRanges(left, right);
        return l != r && l->first <= left && right <= l->second;
    }
    
    void removeRange(int left, int right) {
        auto [l, r] = getOverlapRanges(left, right);
        if (l != r) {
            int lower = min(left, l->first);
            int upper = max(right, prev(r)->second);
            _ranges.erase(l, r);
            if (lower < left) _ranges[lower] = left;
            if (right < upper) _ranges[right] = upper;
        }
    }
};
俄罗斯方块落下后的最大高度
class Solution {
    // left=>[right,height], [left,right)
    map<int, array<int, 2>> _ranges;
    using RI = map<int, array<int, 2>>::iterator;
    array<RI, 2> getOverlapRanges(int left, int right) {
        // 在端点重合处,不认为重叠
        auto l = _ranges.upper_bound(left); // toFind.left>left
        if (l != begin(_ranges) && prev(l)->second[0] > left) // toFind.left<=left&&toFind.right>left
            l = prev(l);
        auto r = _ranges.lower_bound(right); // toFind.left>=right
        return {l, r};
    }
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        vector<int> ans;
        int highest = 0;
        for (auto &pos : positions) {
            int left = pos[0], right = pos[0] + pos[1], height = pos[1];
            auto [l, r] = getOverlapRanges(left, right);
            if (l != r) {
                // 重叠区间的最大高度是新块儿的放置高度
                int baseH = 0;
                for (auto i = l; i != r; i++) {
                    baseH = max(baseH, i->second[1]);
                }
                height += baseH;
                // 删除重叠区间
                int lower = min(left, l->first), lH = l->second[1];
                int upper = max(right, prev(r)->second[0]), rH = prev(r)->second[1];
                _ranges.erase(l, r);
                if (lower < left) _ranges[lower] = {left, lH};
                if (right < upper) _ranges[right] = {upper, rH};
            }
            _ranges[left] = {right, height};

            highest = max(highest, height);
            ans.push_back(highest);
        }
        return ans;
    }
};