This documentation is automatically generated by online-judge-tools/verification-helper
#include "DataStructure/RangeSet.hpp"
#ifndef RangeSet_HPP
#define RangeSet_HPP
/*
verify
・https://atcoder.jp/contests/abc330/tasks/abc330_e
*/
#include <vector>
#include <set>
#include <limits>
#include <iostream>
#include "../Others/macros.hpp"
template <typename T>
struct RangeSet {
private:
std::set<std::pair<T, T>> intervals;
T sum_width;
T TINF = std::numeric_limits<T>::max() / 2;
public:
RangeSet() : sum_width(T(0)) {
intervals.emplace(TINF, TINF); // 番兵
intervals.emplace(-TINF, -TINF); // 番兵
}
/**
* @brief [l, r) が完全に含まれているかどうかを返す
* @param itv 左端が l 以下であるような区間のうち、最も右側にあるもの
*/
bool covered(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return true;
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
return (itv->first <= l) && (r <= itv->second);
}
/**
* @brief x が含まれているかどうかを返す
*/
bool contained(const T& x) {
return covered(x, x + 1);
}
/**
* @brief [l, r) を包含する区間があればその区間を返し、なければ [-INF, -INF) を返す
*/
std::pair<T, T> covered_by(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return std::make_pair(-TINF, -TINF);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) {
return *itv;
}
return std::make_pair(-TINF, -TINF);
}
std::pair<T, T> covered_by(const T& x) {
return covered_by(x, x + 1);
}
/**
* @brief [l, r) を挿入し、区間幅の増分を返す
* l と r それぞれで、l, r を含む区間とマージできるかどうかを見る
*/
T insert(T l, T r) {
assert(l <= r);
if (l == r) {
return T(0);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) {
return T(0); // [l, r) がすでに包含されている場合は例外処理
}
/**
* @param sum_erased_width 消した区間の幅の合計
*/
T sum_erased_width = T(0);
if (itv->first <= l && l <= itv->second) { // l 側で、区間 itv をマージできる場合
l = itv->first;
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
} else { // できなかったら、itr を次の区間に進める
itv = std::next(itv);
}
while (r > itv->second) { // 現時点で [l, r) に包含される区間は全て消す
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
}
if (itv->first <= r && r <= itv->second) { // r 側で、区間 itv をマージできる場合
sum_erased_width += itv->second - itv->first;
r = itv->second;
intervals.erase(itv);
}
intervals.emplace(l, r);
sum_width += r - l - sum_erased_width;
return r - l - sum_erased_width;
}
T insert(const T x) {
return insert(x, x + 1);
}
/**
* @brief [l, r) を削除し、区間幅の減分を返す
*/
T erase(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return T(0);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) { // [l, r) が itv に包含されている場合
if (itv->first < l) { // l 側での itv のはみだし部分が存在する
intervals.emplace(itv->first, l);
}
if (r < itv->second) { // r 側での itv のはみだし部分が存在する
intervals.emplace(r, itv->second);
}
intervals.erase(itv);
sum_width -= r - l;
return r - l;
}
T sum_erased_width = T(0);
if (itv->first <= l && l < itv->second) { // [l, r) が、l 側で itv と共通部分を持つ場合
sum_erased_width += itv->second - l;
if (itv->first < l) { // l 側での itv のはみだし部分が存在する
intervals.emplace(itv->first, l);
}
itv = intervals.erase(itv);
} else {
itv = std::next(itv);
}
while (itv->second <= r) {
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
}
if (itv->first <= r && r < itv->second) { // [l, r) が、l 側で itv と共通部分を持つ場合
sum_erased_width += r - itv->first;
if (r < itv->second) { // r 側での itv のはみだし部分が存在する
intervals.emplace(r, itv->second);
}
intervals.erase(itv);
}
sum_width -= sum_erased_width;
return sum_erased_width;
}
T erase(const T& x) {
return erase(x, x + 1);
}
/**
* @brief 区間の数を返す
*/
int size() const {
return (int)intervals.size() - 2;
}
/**
* x 以上で含まれてない最小の要素は
* ・x が含まれていない:x
* 『・x が含まれている:x を含む区間の末端に 1 加えたもの』
*/
T mex(const T& x = 0) const {
auto itv = std::prev(intervals.upper_bound({x, TINF}));
if (itv->first <= x && x < itv->second) {
return itv->second;
}
return x;
}
/**
* @brief 区間幅の合計を返す
*/
T sum_all() const {
return sum_width;
}
/**
* @brief 全区間を保持した set を返す
*/
std::set<std::pair<T, T>> get_intervals() const {
std::set<std::pair<T, T>> res;
for (const auto& interval : intervals) {
if (std::abs(interval.first) == TINF) {
continue;
}
res.emplace(interval.first, interval.second);
}
return res;
}
void output() const {
for (const auto& interval : intervals) {
if (interval.first == -INF || interval.second == INF) {
continue;
}
std::cout << "[" << interval.first << ", " << interval.second << ")" << '\n';
}
}
};
#endif // RangeSet_HPP
#line 1 "DataStructure/RangeSet.hpp"
/*
verify
・https://atcoder.jp/contests/abc330/tasks/abc330_e
*/
#include <vector>
#include <set>
#include <limits>
#include <iostream>
#line 1 "Others/macros.hpp"
#line 5 "Others/macros.hpp"
#include <queue>
#include <cmath>
using ll = long long;
using lll = __int128_t;
using ld = long double;
#define newl '\n'
#define REF const auto&
#define INF 1000390039
#define LLINF 1000000039000000039
#define IMAX INT_MAX
#define IMIN INT_MIN
#define LLMAX LONG_LONG_MAX
#define LLMIN LONG_LONG_MIN
#define BIT(i) (1LL << (i))
#define tbit(n, k) ((n >> k) & 1) // nの(上から)kビット目
#define bit(n, k) (n & (1LL << (k))) // nの(下から)kビット目
#define PI acos(-1)
#define inr(l, x, r) (l <= x && x < r)
#define einr(l, x, r) (l <= x && x <= r)
#define rep(i, a, b) for(int i = (a); i < (b); i++)
#define erep(i, a, b) for(int i = (a); i <= (b); i++)
#define rrep(i, a, b) for(int i = (a); i >= (b); i--)
#define repl(i, a, b) for(long long i = (a); i < (b); i++)
#define erepl(i, a, b) for(long long i = (a); i <= (b); i++)
#define rrepl(i, a, b) for(long long i = (a); i >= (b); i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define FOR_subset(sub, bit) for (ll sub = (bit); sub >= 0; sub = (sub == 0 ? -1 : (sub - 1) & (bit)))
#define UNIQUE(v) (std::sort(all(v)), (v).erase(std::unique(all(v)), (v).end()))
#define pcnt(x) __builtin_popcount(x)
#define llpcnt(x) __builtin_popcountll(x)
#define VC(name, type, ...) vector<type> name(__VA_ARGS__)
#define VVC(name, type, a, ...) vector<vector<type>> name(a, vector<type>(__VA_ARGS__))
#define VVVC(name, type, a, b, ...) vector<vector<vector<type>>> name(a, vector<vector<type>>(b, vector<type>(__VA_ARGS__)))
#define VVVVC(name, type, a, b, c, ...) vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define VVVVVC(name, type, a, b, c, d, ...) vector<vector<vector<vector<vector<type>>>>> name(a, vector<vector<vector<vector<type>>>>(b, vector<vector<vector<type>>>(c, vector<vector<type>>(d, vector<type>(__VA_ARGS__)))));
template <typename T>
int lwb(const std::vector<T>& vec, const T& x){
return lower_bound(all(vec), x) - vec.begin();
}
template <typename T>
int upb(const std::vector<T>& vec, const T& x){
return upper_bound(all(vec), x) - vec.begin();
}
template <typename T>
T max(const std::vector<T>& vec){ return *max_element(all(vec)); }
template <typename T>
T min(const std::vector<T>& vec){ return *min_element(all(vec)); }
template <typename T>
T rad(const T& x){ return x * PI/180; }
template <typename T>
using maxpq = std::priority_queue<T>;
template <typename T>
using minpq = std::priority_queue<T, std::vector<T>, std::greater<T>>;
// 最大値・最小値の更新
template <typename T1, typename T2>
bool chmax(T1 &a, const T2& b){
if (a < b) { a = b; return 1; }
return 0;
}
template <typename T1, typename T2>
bool chmin(T1 &a, const T2& b){
if (a > b) { a = b; return 1; }
return 0;
}
const int di4[4] = {-1, 0, 1, 0};
const int dj4[4] = {0, 1, 0, -1};
const int di8[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
const int dj8[8] = {0, 1, 1, 1, 0, -1, -1, -1};
bool out_of_grid(const int& i, const int& j, const int& h, const int& w){
if(i < 0 || j < 0 || i >= h || j >= w) return true;
return false;
}
#line 15 "DataStructure/RangeSet.hpp"
template <typename T>
struct RangeSet {
private:
std::set<std::pair<T, T>> intervals;
T sum_width;
T TINF = std::numeric_limits<T>::max() / 2;
public:
RangeSet() : sum_width(T(0)) {
intervals.emplace(TINF, TINF); // 番兵
intervals.emplace(-TINF, -TINF); // 番兵
}
/**
* @brief [l, r) が完全に含まれているかどうかを返す
* @param itv 左端が l 以下であるような区間のうち、最も右側にあるもの
*/
bool covered(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return true;
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
return (itv->first <= l) && (r <= itv->second);
}
/**
* @brief x が含まれているかどうかを返す
*/
bool contained(const T& x) {
return covered(x, x + 1);
}
/**
* @brief [l, r) を包含する区間があればその区間を返し、なければ [-INF, -INF) を返す
*/
std::pair<T, T> covered_by(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return std::make_pair(-TINF, -TINF);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) {
return *itv;
}
return std::make_pair(-TINF, -TINF);
}
std::pair<T, T> covered_by(const T& x) {
return covered_by(x, x + 1);
}
/**
* @brief [l, r) を挿入し、区間幅の増分を返す
* l と r それぞれで、l, r を含む区間とマージできるかどうかを見る
*/
T insert(T l, T r) {
assert(l <= r);
if (l == r) {
return T(0);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) {
return T(0); // [l, r) がすでに包含されている場合は例外処理
}
/**
* @param sum_erased_width 消した区間の幅の合計
*/
T sum_erased_width = T(0);
if (itv->first <= l && l <= itv->second) { // l 側で、区間 itv をマージできる場合
l = itv->first;
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
} else { // できなかったら、itr を次の区間に進める
itv = std::next(itv);
}
while (r > itv->second) { // 現時点で [l, r) に包含される区間は全て消す
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
}
if (itv->first <= r && r <= itv->second) { // r 側で、区間 itv をマージできる場合
sum_erased_width += itv->second - itv->first;
r = itv->second;
intervals.erase(itv);
}
intervals.emplace(l, r);
sum_width += r - l - sum_erased_width;
return r - l - sum_erased_width;
}
T insert(const T x) {
return insert(x, x + 1);
}
/**
* @brief [l, r) を削除し、区間幅の減分を返す
*/
T erase(const T& l, const T& r) {
assert(l <= r);
if (l == r) {
return T(0);
}
auto itv = std::prev(intervals.upper_bound(std::make_pair(l, TINF)));
if (itv->first <= l && r <= itv->second) { // [l, r) が itv に包含されている場合
if (itv->first < l) { // l 側での itv のはみだし部分が存在する
intervals.emplace(itv->first, l);
}
if (r < itv->second) { // r 側での itv のはみだし部分が存在する
intervals.emplace(r, itv->second);
}
intervals.erase(itv);
sum_width -= r - l;
return r - l;
}
T sum_erased_width = T(0);
if (itv->first <= l && l < itv->second) { // [l, r) が、l 側で itv と共通部分を持つ場合
sum_erased_width += itv->second - l;
if (itv->first < l) { // l 側での itv のはみだし部分が存在する
intervals.emplace(itv->first, l);
}
itv = intervals.erase(itv);
} else {
itv = std::next(itv);
}
while (itv->second <= r) {
sum_erased_width += itv->second - itv->first;
itv = intervals.erase(itv);
}
if (itv->first <= r && r < itv->second) { // [l, r) が、l 側で itv と共通部分を持つ場合
sum_erased_width += r - itv->first;
if (r < itv->second) { // r 側での itv のはみだし部分が存在する
intervals.emplace(r, itv->second);
}
intervals.erase(itv);
}
sum_width -= sum_erased_width;
return sum_erased_width;
}
T erase(const T& x) {
return erase(x, x + 1);
}
/**
* @brief 区間の数を返す
*/
int size() const {
return (int)intervals.size() - 2;
}
/**
* x 以上で含まれてない最小の要素は
* ・x が含まれていない:x
* 『・x が含まれている:x を含む区間の末端に 1 加えたもの』
*/
T mex(const T& x = 0) const {
auto itv = std::prev(intervals.upper_bound({x, TINF}));
if (itv->first <= x && x < itv->second) {
return itv->second;
}
return x;
}
/**
* @brief 区間幅の合計を返す
*/
T sum_all() const {
return sum_width;
}
/**
* @brief 全区間を保持した set を返す
*/
std::set<std::pair<T, T>> get_intervals() const {
std::set<std::pair<T, T>> res;
for (const auto& interval : intervals) {
if (std::abs(interval.first) == TINF) {
continue;
}
res.emplace(interval.first, interval.second);
}
return res;
}
void output() const {
for (const auto& interval : intervals) {
if (interval.first == -INF || interval.second == INF) {
continue;
}
std::cout << "[" << interval.first << ", " << interval.second << ")" << '\n';
}
}
};