m1une's library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: Merge Intervals
(algo/sequence/merge_intervals.hpp)

Overview

Computes the union of half-open intervals. The result is sorted by left endpoint, contains no empty intervals, and has a positive gap between every two consecutive intervals. In particular, overlapping or touching intervals are merged.

Every input interval must satisfy left <= right. Endpoints must be movable and support a strict weak ordering through operator<; passing an lvalue vector also requires them to be copyable.

Functions

Function Description Complexity
vector<pair<T, T>> merge_intervals(vector<pair<T, T>> intervals) Returns the union of the half-open intervals [left, right). The argument is copied when an lvalue is passed and can be consumed with std::move. $O(N \log N)$ time and $O(1)$ auxiliary space

Notes

Example

#include "algo/sequence/merge_intervals.hpp"

#include <utility>
#include <vector>

int main() {
    std::vector<std::pair<int, int>> intervals;
    intervals.emplace_back(5, 8);
    intervals.emplace_back(1, 3);
    intervals.emplace_back(3, 6);
    intervals.emplace_back(9, 9);

    auto merged = m1une::algo::merge_intervals(intervals);
    // merged contains [1, 8).
}

Required by

Verified with

Code

#ifndef M1UNE_ALGO_SEQUENCE_MERGE_INTERVALS_HPP
#define M1UNE_ALGO_SEQUENCE_MERGE_INTERVALS_HPP 1

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <utility>
#include <vector>

namespace m1une {
namespace algo {

// Returns the union of half-open intervals as sorted, disjoint intervals.
template <typename T>
std::vector<std::pair<T, T>> merge_intervals(
    std::vector<std::pair<T, T>> intervals
) {
    for (const auto& [left, right] : intervals) {
        if (right < left) assert(false);
    }

    std::sort(
        intervals.begin(),
        intervals.end(),
        [](const auto& lhs, const auto& rhs) {
            if (lhs.first < rhs.first) return true;
            if (rhs.first < lhs.first) return false;
            return lhs.second < rhs.second;
        }
    );

    std::size_t result_size = 0;
    for (std::size_t index = 0; index < intervals.size(); ++index) {
        auto& [left, right] = intervals[index];
        if (!(left < right)) continue;
        if (result_size == 0 || intervals[result_size - 1].second < left) {
            if (result_size != index) {
                intervals[result_size] = std::move(intervals[index]);
            }
            ++result_size;
        } else if (intervals[result_size - 1].second < right) {
            intervals[result_size - 1].second = std::move(right);
        }
    }
    intervals.erase(intervals.begin() + result_size, intervals.end());
    return intervals;
}

}  // namespace algo
}  // namespace m1une

#endif  // M1UNE_ALGO_SEQUENCE_MERGE_INTERVALS_HPP
#line 1 "algo/sequence/merge_intervals.hpp"



#include <algorithm>
#include <cassert>
#include <cstddef>
#include <utility>
#include <vector>

namespace m1une {
namespace algo {

// Returns the union of half-open intervals as sorted, disjoint intervals.
template <typename T>
std::vector<std::pair<T, T>> merge_intervals(
    std::vector<std::pair<T, T>> intervals
) {
    for (const auto& [left, right] : intervals) {
        if (right < left) assert(false);
    }

    std::sort(
        intervals.begin(),
        intervals.end(),
        [](const auto& lhs, const auto& rhs) {
            if (lhs.first < rhs.first) return true;
            if (rhs.first < lhs.first) return false;
            return lhs.second < rhs.second;
        }
    );

    std::size_t result_size = 0;
    for (std::size_t index = 0; index < intervals.size(); ++index) {
        auto& [left, right] = intervals[index];
        if (!(left < right)) continue;
        if (result_size == 0 || intervals[result_size - 1].second < left) {
            if (result_size != index) {
                intervals[result_size] = std::move(intervals[index]);
            }
            ++result_size;
        } else if (intervals[result_size - 1].second < right) {
            intervals[result_size - 1].second = std::move(right);
        }
    }
    intervals.erase(intervals.begin() + result_size, intervals.end());
    return intervals;
}

}  // namespace algo
}  // namespace m1une
Back to top page