Skip to content

Interval set

C++

template<class T = int>
struct IntervalSet {
    using I = std::pair<T, T>;
    IntervalSet(T neg_inf): neg_inf(neg_inf) {}

    void insert(T l, T r) {
        T new_l = l, new_r = r;
        auto itr = st.lower_bound(I(l, neg_inf));
        while(itr != st.end() and (*itr).second <= new_r) {
            new_l = std::min(new_l, (*itr).second);
            new_r = std::max(new_r, (*itr).first);
            st.erase(itr++);
        }
        st.insert(I(new_r, new_l));
    }

    void erase(T l, T r) {
        auto itr = st.lower_bound(I(l, l));
        std::vector<I> v;
        while(itr != st.end() and (*itr).second < r) {
            v.push_back(*itr);
            st.erase(itr++);
        }
        for(auto [s, e] : v) {
            if(l <= s and e <= r) continue;
            if(s < l) st.insert(I(l, s));
            if(r < e) st.insert(I(e, r));
        }
    }

    size_t size() {
        return st.size();
    }

    bool is_covered(T x) {
        // x がある区間で覆われているか
        auto itr = st.lower_bound(I(x, x));
        if(itr == st.end()) return false;
        T l = (*itr).second, r = (*itr).first;
        return l <= x and x < r;
    }

    I is_covered_by(T x) {
        // x を覆っている区間, 存在しなければ [neg_inf, neg_inf) を返す
        auto itr = st.lower_bound(I(x, x));
        if(itr == st.end()) return I(neg_inf, neg_inf);
        T l = (*itr).second, r = (*itr).first;
        if(l <= x and x < r) return I(l, r);
        return I(neg_inf, neg_inf);
    }
  private:
    std::set<I> st;
    T neg_inf; // -inf
};