Skip to content

Instantly share code, notes, and snippets.

@Ryoga-exe
Last active October 23, 2022 18:27
Show Gist options
  • Save Ryoga-exe/caa449d5f5c69c0baa1c94bfc674b5ec to your computer and use it in GitHub Desktop.
Save Ryoga-exe/caa449d5f5c69c0baa1c94bfc674b5ec to your computer and use it in GitHub Desktop.
WIP
# include <cstdint>
# include <iostream>
# include <vector>
# include <cassert>
# include <set>
namespace Ryoga_exe
{
using int32 = std::int32_t;
using int64 = std::int64_t;
template <class Type> using Array = std::vector<Type>;
template <class Type>
class RangeSet
{
public:
using value_type = Type;
using range_type = std::pair<value_type, value_type>;
using container_type = std::set<range_type>;
using iterator = typename container_type::iterator;
using size_type = typename container_type::size_type;
private:
container_type m_set;
public:
explicit constexpr RangeSet() = default;
iterator begin() const noexcept
{
return m_set.begin();
}
iterator end() const noexcept
{
return m_set.end();
}
bool isEmpty() const noexcept
{
return m_set.empty();
}
// numRanges
size_type size() const noexcept
{
return m_set.size();
}
value_type length() const noexcept
{
value_type result = 0;
for (const auto& [l, r] : m_set)
{
result += (r - l);
}
return result;
}
container_type asSet() const noexcept
{
return m_set;
}
Array<range_type> asArray() const noexcept
{
Array<range_type> result;
for (const auto range : m_set)
{
result.push_back(range);
}
return result;
}
std::pair<iterator, bool> insert(value_type left, value_type right)
{
assert(left <= right);
if (left == right)
{
return { m_set.end(), false };
}
auto itr = m_set.lower_bound({ left, right });
if (itr != m_set.end() && itr->first == left)
{
return { itr, false };
}
if (itr != m_set.begin())
{
if (const auto prev_itr = std::prev(itr); prev_itr->first != left && right <= prev_itr->second)
{
return { std::prev(itr), false };
}
}
itr = m_set.emplace_hint(itr, left, right);
while (itr != std::prev(m_set.end()) && std::next(itr)->first <= itr->second)
{
if (std::next(itr)->second <= itr->second)
{
m_set.erase(std::next(itr));
}
else
{
itr = m_set.emplace_hint(std::next(itr), itr->first, std::next(itr)->second);
m_set.erase(std::prev(itr));
m_set.erase(std::next(itr));
}
}
while (itr != m_set.begin() && itr->first <= std::prev(itr)->second)
{
if (itr->first == std::prev(itr)->first)
{
m_set.erase(std::prev(itr));
}
else
{
itr = m_set.emplace_hint(itr, std::prev(itr)->first, itr->second);
m_set.erase(std::prev(itr));
m_set.erase(std::next(itr));
}
}
return { itr, true };
}
// 整数型のみ
void insert(value_type value)
{
return insert(value, value + 1);
}
void erase(value_type left, value_type right)
{
assert(left <= right);
if (left == right)
{
return;
}
auto itl = m_set.upper_bound({ left, left });
auto itr = m_set.upper_bound({ right, right });
if (itl != m_set.begin())
{
if (std::prev(itl)->second >= left)
{
itl--;
}
}
if (itl == itr)
{
return;
}
auto tl = std::min(left, itl->first);
auto tr = std::max(right, std::prev(itr)->second);
m_set.erase(itl, itr);
if (tl < left)
{
m_set.insert({ tl, left });
}
if (right < tr)
{
m_set.insert({ right, tr });
}
}
// 整数型のみ
void erase(value_type value)
{
return erase(value, value + 1);
}
};
}
int main()
{
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment