This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
#include "utils/interval_map.hpp"
#pragma once #include <map> #include <optional> #include <tuple> #include <vector> /** * @brief map from disjoint intervals */ template <class T> class interval_map { std::map<int64_t, std::pair<int64_t, T> > data; // the function which from right terminals r_i to the pairs (l_i, value) of left terminals l_i of intervals [l_i, r_i) public: /** * @note O(\log q) amortized * @note [l_i, r_i) */ void update_interval(int64_t l, int64_t r, T value) { assert (l <= r); if (l == r) return; auto it = data.lower_bound(l); if (it != data.end() and it->second.first < l) { auto r2 = it->first; auto [l2, value2] = it->second; if (r < r2) { // included if (value2 == value) { return; } else { it->second.first = r; data.emplace(l, std::make_pair(l2, value2)); } } else { if (value2 == value) { l = l2; data.erase(it); } else if (l < r2) { data.erase(it); data.emplace(l, std::make_pair(l2, value2)); } } } while (true) { it = data.upper_bound(l); if (it == data.end() or r < it->second.first) { break; } auto r2 = it->first; auto [l2, value2] = it->second; assert (l <= l2); if (r2 <= r) { data.erase(it); } else { if (value2 == value) { r = r2; data.erase(it); } else if (l2 < r) { it->second.first = r; } break; } } data.emplace(r, std::make_pair(l, value)); } /** * @note O(\log q) */ void remove_containing_interval(int64_t x) { auto it = data.upper_bound(x); if (it != data.end() and it->second <= x) { data.erase(it); } } /** * @note O(\log q) */ std::optional<T> find_value(int64_t x) const { auto it = data.upper_bound(x); if (it != data.end() and it->second.first <= x) { return std::make_optional(it->second.second); } else { return std::optional<T>(); } } /** * @note O(\log q) */ std::optional<std::tuple<int64_t, int64_t, T> > find_containing_interval(int64_t x) const { auto it = data.upper_bound(x); if (it != data.end() and it->second.first <= x) { return std::make_optional(std::make_tuple(it->second.first, it->first, it->second.second)); } else { return std::optional<std::tuple<int64_t, int64_t, T> >(); } } /** * @note O(k \log q) * @note [l_i, r_i) */ std::vector<std::tuple<int64_t, int64_t, T> > list_intersecting_interval(int64_t l, int64_t r) const { assert (l <= r); std::vector<std::tuple<int64_t, int64_t, T> > result; while (true) { auto it = data.upper_bound(l); if (it == data.end() or r <= it->second.first) { break; } result.emplace_back(it->second.first, it->first, it->second.second); l = it->first; } return result; } };
#line 2 "utils/interval_map.hpp" #include <map> #include <optional> #include <tuple> #include <vector> /** * @brief map from disjoint intervals */ template <class T> class interval_map { std::map<int64_t, std::pair<int64_t, T> > data; // the function which from right terminals r_i to the pairs (l_i, value) of left terminals l_i of intervals [l_i, r_i) public: /** * @note O(\log q) amortized * @note [l_i, r_i) */ void update_interval(int64_t l, int64_t r, T value) { assert (l <= r); if (l == r) return; auto it = data.lower_bound(l); if (it != data.end() and it->second.first < l) { auto r2 = it->first; auto [l2, value2] = it->second; if (r < r2) { // included if (value2 == value) { return; } else { it->second.first = r; data.emplace(l, std::make_pair(l2, value2)); } } else { if (value2 == value) { l = l2; data.erase(it); } else if (l < r2) { data.erase(it); data.emplace(l, std::make_pair(l2, value2)); } } } while (true) { it = data.upper_bound(l); if (it == data.end() or r < it->second.first) { break; } auto r2 = it->first; auto [l2, value2] = it->second; assert (l <= l2); if (r2 <= r) { data.erase(it); } else { if (value2 == value) { r = r2; data.erase(it); } else if (l2 < r) { it->second.first = r; } break; } } data.emplace(r, std::make_pair(l, value)); } /** * @note O(\log q) */ void remove_containing_interval(int64_t x) { auto it = data.upper_bound(x); if (it != data.end() and it->second <= x) { data.erase(it); } } /** * @note O(\log q) */ std::optional<T> find_value(int64_t x) const { auto it = data.upper_bound(x); if (it != data.end() and it->second.first <= x) { return std::make_optional(it->second.second); } else { return std::optional<T>(); } } /** * @note O(\log q) */ std::optional<std::tuple<int64_t, int64_t, T> > find_containing_interval(int64_t x) const { auto it = data.upper_bound(x); if (it != data.end() and it->second.first <= x) { return std::make_optional(std::make_tuple(it->second.first, it->first, it->second.second)); } else { return std::optional<std::tuple<int64_t, int64_t, T> >(); } } /** * @note O(k \log q) * @note [l_i, r_i) */ std::vector<std::tuple<int64_t, int64_t, T> > list_intersecting_interval(int64_t l, int64_t r) const { assert (l <= r); std::vector<std::tuple<int64_t, int64_t, T> > result; while (true) { auto it = data.upper_bound(l); if (it == data.end() or r <= it->second.first) { break; } result.emplace_back(it->second.first, it->first, it->second.second); l = it->first; } return result; } };