matsutaku-library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub MatsuTaku/matsutaku-library

:heavy_check_mark: test/standalone/integer_set_test.cpp

Depends on

Code

#define STANDALONE
#include "include/mtl/integer_set.hpp"
#include "set_test.hpp"

constexpr int W = 20;
//constexpr int Max = 4e5;
//
//template<typename Set>
//int test_set() {
//  std::vector<int> values;
//  while (values.empty()) {
//    for (int i = 0; i < Max; i++) {
//      if (i == 0 or rand()%4 == 0)
//        values.push_back(i);
//    }
//  }
//  int n = values.size();
//  std::vector<int> shuffled = values;
//  for (int i = 0; i < n; i++) {
//    std::swap(shuffled[i], shuffled[rand()%n]);
//  }
//
//  Set S;
//  for (int v : shuffled) {
//    S.insert(v);
//  }
////  S.print_for_debug();
//  int target = -1;
//  int pred = -1;
//  int succ = values[0];
//  int k = 0;
//  auto log = [&]() {
//    std::cout << pred << ' ' << target << ' ' << succ << std::endl;
//    assert(false);
//  };
//  for (int i = 0; i < Max; i++) {
//    if (k < n and values[k] == i) {
//      target = values[k];
//      pred = k-1 >= 0 ? values[k-1] : -1;
//      succ = k+1 < n ? values[k+1] : -1;
//      k++;
//    } else {
//      pred = k-1 >= 0 ? values[k-1] : -1;
//      target = -1;
//    }
//
//    auto fit = S.find(i);
//    if (fit != S.end()) {
//      if ((int) *fit != i) {
//        std::cout << "find: " << i << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (target != -1) {
//        log();
//        return 1;
//      }
//    }
//
//    auto sucit = S.successor(i);
//    if (sucit != S.end()) {
//      if ((int) *sucit != succ) {
//        std::cout << "succ: " << *sucit << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (succ != -1) {
//        log();
//        return 1;
//      }
//    }
//
//    auto predit = S.predecessor(i);
//    if (predit != S.end()) {
//      if ((int) *predit != pred) {
//        std::cout << "pred: " << *predit << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (pred != -1) {
//        log();
//        return 1;
//      }
//    }
//  }
//
//  int size = n;
//  if ((int) S.size() != size) {
//    std::cout << S.size() << ' ' << size<< std::endl;
//    log();
//    return 1;
//  }
//  for (int v : shuffled) {
//    S.erase(v);
//    size--;
//    if ((int) S.size() != size) {
//      std::cout << S.size() << ' ' << size<< std::endl;
//      assert(false);
//      return 1;
//    }
//  }
//  return 0;
//}

int main() {
//  mtl::integer_set_test<XFastTrieSet<W>>();
//  mtl::integer_set_test<YFastTrieSet<W>>();
  std::cout << "OK" << std::endl;
}
#line 1 "test/standalone/integer_set_test.cpp"
#define STANDALONE
#line 2 "include/mtl/treap.hpp"
#include <memory>
#include <iterator>
#include <cassert>
#include <exception>
#include <random>
#include <iostream>

template<class T, class V=void,
    class Compare = std::less<>,
    bool UniqueKey = true>
class Treap {
 public:
  using key_type = T;
  static constexpr bool kKeyOnly = std::is_same<V, void>::value;
  using mapped_type = typename std::conditional<kKeyOnly, T, V>::type;
  using value_type = typename std::conditional<
      kKeyOnly,
      T,
      std::pair<T const, V>
  >::type;
  using raw_key_type = typename std::conditional<kKeyOnly, T, typename std::remove_const<T>::type>::type;
  using raw_value_type = typename std::conditional<kKeyOnly, T, typename std::remove_const<V>::type>::type;
  using init_type = typename std::conditional<
      kKeyOnly,
      T,
      std::pair<raw_key_type, raw_value_type>
  >::type;
  using priority_type = uint32_t;
 protected:
  template<bool> struct iterator_base;
 public:
  using iterator = iterator_base<false>;
  using const_iterator = iterator_base<true>;
 private:
  struct Node;
  using node_ptr = std::shared_ptr<Node>;
  using node_weak = std::weak_ptr<Node>;
  struct Node {
    node_ptr left, right;
    node_weak parent;
    priority_type p;
    value_type v;
    explicit Node(priority_type p)
      : left(nullptr), right(nullptr), p(p) {}
    explicit Node(priority_type p, const value_type& v)
        : left(nullptr), right(nullptr), p(p), v(v) {}
    explicit Node(priority_type p, value_type&& v)
        : left(nullptr), right(nullptr), p(p), v(std::forward<value_type>(v)) {}
    template<typename... Args>
    explicit Node(priority_type p, Args&&... args)
        : left(nullptr), right(nullptr), p(p),
          v(std::forward<Args>(args)...) {}
    const raw_key_type& key() const {
      if constexpr (kKeyOnly)
        return v;
      else
        return v.first;
    }
  };
  node_ptr sentinel_;
  size_t size_;
  std::default_random_engine eng;
  std::uniform_int_distribution<priority_type> dist;
  Compare comp_;

 public:
  Treap(const Compare& comp = Compare())
      : sentinel_(std::make_shared<Node>(0)), size_(0),
        comp_(comp) {}
  template<typename It>
  explicit Treap(It begin, It end,
                 const Compare& comp = Compare()) : Treap(comp) {
    insert(begin, end);
  }
  Treap(std::initializer_list<value_type> list) : Treap(list.begin(), list.end()) {}
 private:
  void _clone(node_ptr u, const node_ptr ru) {
    if (ru->left) {
      u->left = std::make_shared<Node>(ru->left->p, ru->left->v);
      u->left->parent = u;
      _clone(u->left, ru->left);
    }
    if (ru->right) {
      u->right = std::make_shared<Node>(ru->right->p, ru->right->v);
      u->right->parent = u;
      _clone(u->right, ru->right);
    }
  }
 public:
  Treap(const Treap& r) : Treap() {
    _clone(sentinel_, r.sentinel_);
    size_ = r.size_;
  }
  Treap& operator=(const Treap& r) {
    clear();
    _clone(sentinel_, r.sentinel_);
    size_ = r.size_;
    return *this;
  }
  Treap(Treap&& r) noexcept = default;
  Treap& operator=(Treap&& r) noexcept = default;

 private:
  bool _check_connection(node_ptr u) const {
    if (!u)
      return false;
    assert(u != sentinel_ or sentinel_->right == nullptr);
    if (u == sentinel_ and u->right)
      return true;
    if (u->left)  {
      assert(u->left->parent == u);
      if (!(u->left->parent == u))
        return true;
    }
    if (u->right) {
      assert(u->right->parent == u);
      if (!(u->right->parent == u))
        return true;
    }
    if (_check_connection(u->left))
      return true;
    if (_check_connection(u->right))
      return true;
    return false;
  }
  node_ptr _root() const {
    return sentinel_->left;
  }
  priority_type _pick_priority() { return dist(eng); }
  bool _comp_priority(node_ptr u, node_ptr v) const {
    return u->p < v->p;
  }
  void _turn_left(node_ptr u) {
    auto p = u->parent.lock();
    auto r = u->right;
    assert(p);
    assert(r);
    if (p->left == u)
      p->left = r;
    else {
      assert(p->right == u);
      p->right = r;
    }
    r->parent = p;
    auto rl = r->left;
    u->right = rl;
    if (rl) rl->parent = u;
    r->left = u;
    u->parent = r;
  }
  void _turn_right(node_ptr u) {
    auto p = u->parent.lock();
    auto l = u->left;
    assert(p);
    assert(l);
    if (p->left == u)
      p->left = l;
    else {
      assert(p->right == u);
      p->right = l;
    }
    l->parent = p;
    auto lr = l->right;
    u->left = lr;
    if (lr) lr->parent = u;
    l->right = u;
    u->parent = l;
  }
  template<typename Cond>
  void _bubble_up_cond(node_ptr u, Cond cond) {
    while (cond(u)) {
      assert(!u->parent.expired());
      auto p = u->parent.lock();
      assert(p != sentinel_);
      if (p->right == u) {
        _turn_left(p);
      } else {
        assert(p->left == u);
        _turn_right(p);
      }
    }
  }
  void _bubble_up(node_ptr u) {
    _bubble_up_cond(u, [&](node_ptr u) { return _comp_priority(u, u->parent.lock()); });
  }
  void _bubble_up_force(node_ptr u) {
    _bubble_up_cond(u, [&](node_ptr u) { return u->parent.lock() != sentinel_; });
    assert(u->parent.lock() == sentinel_);
    assert(_root() == u);
  }
  void _tricle_down(node_ptr u) {
    while (u->left or u->right) {
      if (!u->right) {
        _turn_right(u);
      } else if (!u->left) {
        _turn_left(u);
      } else if (_comp_priority(u->left, u->right)) {
        _turn_right(u);
      } else {
        _turn_left(u);
      }
    }
  }
  // Used for leaf only (done after _tricle_down)
  void _splice(node_ptr u) {
    assert(!u->left and !u->right);
    auto p = u->parent.lock();
    assert(p);
    if (p->left == u)
      p->left = nullptr;
    else {
      assert(p->right == u);
      p->right = nullptr;
    }
    u->parent.reset();
  }
  // NOTE: value of size_ is broken.
  Treap(node_ptr node) : Treap() {
    sentinel_->left = node;
    if (node)
      node->parent = sentinel_;
  }
  std::pair<iterator, bool> _insert_node_subtree(node_ptr u, node_ptr new_node) {
    auto x = new_node->key();
    while (true) {
      if constexpr (UniqueKey) if (u != sentinel_ and x == u->key())
        return std::make_pair(iterator(u), false);
      auto& c = u == sentinel_ or comp_(x, u->key()) ? u->left : u->right;
      if (!c) {
        c = new_node;
        c->parent = u;
        u = c;
        break;
      } else {
        u = c;
      }
    }
    _bubble_up(u);
    ++size_;
    return std::make_pair(iterator(u), true);
  }
  std::pair<iterator, bool> _insert_node(node_ptr new_node) {
    return _insert_node_subtree(sentinel_, new_node);
  }
  iterator _insert_node_hint(const_iterator hint, node_ptr new_node) {
    auto x = new_node->key();
    auto u = hint.ptr_;
    if (!u->parent.expired()) {
      auto p = u->parent.lock();
      if (p != sentinel_) {
        T xp = p->key();
        if constexpr (UniqueKey) if (xp == x) [[unlikely]]
          return iterator(p);
        // Check hint is malicious
        if (   (p->left == u and comp_(xp, x))
            or (p->right == u and comp_(x, xp))) [[unlikely]]
          return _insert_node(new_node).first;
        //
      }
    }
    return _insert_node_subtree(u, new_node).first;
  }

 public:
  size_t size() const { return size_; } // TODO: split break size
  bool empty() const { return _root() == nullptr; }
  void clear() {
    sentinel_->left = nullptr;
    size_ = 0;
  }

  iterator find(T x) const {
    node_ptr u = _root();
    while (u) {
      if (u->key() == x)
        return iterator(u);
      if (comp_(x, u->key()))
        u = u->left;
      else
        u = u->right;
    }
    return end();
  }
  size_t count(T x) const { return (size_t) (find(x) != end()); }
  iterator lower_bound(T x) const {
    node_ptr u = _root();
    node_ptr lb = sentinel_;
    while (u) {
      if (u->key() == x)
        return iterator(u);
      if (comp_(x, u->key())) {
        lb = u;
        u = u->left;
      } else {
        u = u->right;
      }
    }
    return iterator(lb);
  }
  iterator upper_bound(T x) const {
    node_ptr u = _root();
    node_ptr ub = sentinel_;
    while (u) {
      if (comp_(x, u->key())) {
        ub = u;
        u = u->left;
      } else {
        u = u->right;
      }
    }
    return iterator(ub);
  }
  iterator successor(T x) const { return upper_bound(x); }
  iterator predecessor(T x) const {
    auto u = _root();
    node_ptr pr = sentinel_;
    while (u) {
      if (!comp_(u->key(), x)) {
        u = u->left;
      } else {
        pr = u;
        u = u->right;
      }
    }
    return iterator(pr);
  }

 private:
  template<typename... Args>
  node_ptr _create_node(Args&&... args) {
    auto p = _pick_priority();
    return std::make_shared<Node>(p, std::forward<Args>(args)...);
  }
 public:
  template<typename ...Args>
  std::pair<iterator, bool> emplace(Args&&... args) {
    return _insert_node(_create_node(std::forward<Args>(args)...));
  }
  template<typename ...Args>
  iterator emplace_hint(const_iterator hint, Args&&... args) {
    return _insert_node_hint(hint, _create_node(std::forward<Args>(args)...));
  }
  std::pair<iterator, bool> insert(const init_type& e) {
    return emplace(e);
  }
  std::pair<iterator, bool> insert(init_type&& e) {
    return emplace(std::move(e));
  }
  template<typename=void>
  std::pair<iterator, bool> insert(const value_type& e) {
    return emplace(e);
  }
  template<typename=void>
  std::pair<iterator, bool> insert(value_type&& e) {
    return emplace(std::move(e));
  }
  template<class It>
  void insert(It begin, It end) {
    using traits = std::iterator_traits<It>;
    static_assert(std::is_convertible<typename traits::value_type, value_type>::value, "");
    static_assert(std::is_base_of<std::forward_iterator_tag, typename traits::iterator_category>::value, "");
    for (auto it = begin; it != end; ++it)
      emplace(*it);
  }
  void insert(std::initializer_list<value_type> list) {
    insert(list.begin(), list.end());
  }

  iterator erase(iterator it) {
    if (it == end())
      return end();
    auto u = it.ptr_;
    auto p = u->parent;
    _tricle_down(u);
    auto ret = ++iterator(u);
    _splice(u);
    --size_;
    return ret;
  }
  bool erase(T x) {
    auto it = find(x);
    if (it != end()) {
      erase(it);
      return 1;
    } else {
      return 0;
    }
  }
  iterator erase(iterator begin, iterator end) {
    auto _l = split(begin);
    auto _m = split(end);
    return absorb(&_l);
  }

  [[nodiscard]] Treap split(iterator it) {
    // !!! Breaking size_ value !!!
    auto u = it.ptr_;
    auto d = std::make_shared<Node>(std::numeric_limits<priority_type>::max());
    auto lu = u->left;
    d->left = lu;
    d->parent = u;
    u->left = d;
    if (lu) lu->parent = d;
    _bubble_up_force(d);
    auto l = d->left;
    auto r = d->right;
    sentinel_->left = r;
    if (r) r->parent = sentinel_;
    if (l) l->parent.reset();
    return Treap(l);
  }
  iterator absorb(Treap* s) {
    assert((s and s->empty()) or empty() or comp_(*--s->end(), *begin()));
    auto it = begin();
    if (!s or s->empty()) return it;
    if (empty()) {
      sentinel_->left = s->_root();
      sentinel_->left->parent = sentinel_;
      size_ = s->size_;
      s->clear();
      return begin();
    }
    auto d = std::make_shared<Node>(0);
    d->left = s->_root();
    d->right = _root();
    d->parent = sentinel_;
    if (d->left)
      d->left->parent = d;
    if (d->right)
      d->right->parent = d;
    sentinel_->left = d;
    _tricle_down(d);
    _splice(d);
    size_ += s->size_;
    s->clear();
    return it;
  }

 protected:
  template<bool Const>
  struct iterator_base {
   public:
    using difference_type = ptrdiff_t;
    using value_type = Treap::value_type;
    using pointer = typename std::conditional<Const,
                                              const value_type*,
                                              value_type*>::type;
    using reference = typename std::conditional<Const,
                                                const value_type&,
                                                value_type&>::type;
    using iterator_category = std::bidirectional_iterator_tag;
   private:
    node_ptr ptr_;
    friend class Treap;
   public:
    explicit iterator_base(node_ptr ptr) : ptr_(ptr) {}
    template<bool C>
    iterator_base(const iterator_base<C>& rhs) : ptr_(rhs.ptr_) {}
    template<bool C>
    iterator_base& operator=(const iterator_base<C>& rhs) {
      ptr_ = rhs.ptr_;
      return *this;
    }
    template<bool C>
    iterator_base(iterator_base<C>&& rhs) : ptr_(std::move(rhs.ptr_)) {}
    template<bool C>
    iterator_base& operator=(iterator_base<C>&& rhs) {
      ptr_ = std::move(rhs.ptr_);
      return *this;
    }
    template<bool C>
    bool operator==(const iterator_base<C>& r) const { 
      return ptr_ == r.ptr_;
    }
    template<bool C>
    bool operator!=(const iterator_base<C>& r) const { 
      return ptr_ != r.ptr_;
    }
    reference operator*() const { return ptr_->v; }
    pointer operator->() const { return &(ptr_->v); }
    iterator_base& operator++() {
      auto u = ptr_;
      if (u->right) {
        u = u->right;
        while (u->left)
          u = u->left;
        ptr_ = u;
      } else {
        node_ptr p;
        while ((p = u->parent.lock()) and p->left != u) {
          u = p;
        }
        assert(!u->parent.expired());
        assert(u->parent.lock()->left == u);
        ptr_ = u->parent.lock();
      }
      return *this;
    }
    iterator_base operator++(int) {
      iterator ret = *this;
      ++*this;
      return ret;
    }
    iterator_base& operator--() {
      auto u = ptr_;
      if (u->left) {
        u = u->left;
        while (u->right)
          u = u->right;
        ptr_ = u;
      } else {
        node_ptr p;
        while ((p = u->parent.lock()) and p->right != u) {
          u = p;
        }
        ptr_ = u->parent.lock();
      }
      return *this;
    }
    iterator_base operator--(int) {
      iterator ret = *this;
      --*this;
      return ret;
    }
  };
 public:
  const_iterator begin() const {
    auto u = sentinel_;
    while (u->left)
      u = u->left;
    return const_iterator(u);
  };
  const_iterator end() const {
    return const_iterator(sentinel_);
  };
  const_iterator cbegin() const {
    return begin();
  }
  const_iterator cend() const {
    return end();
  }
  iterator begin() {
    return iterator(cbegin());
  };
  iterator end() {
    return iterator(cend());
  };
  void print_for_debug(node_ptr u = nullptr, int depth = -1) const {
    if (_root())
      std::cout<<_root()->key()<<std::endl;
    auto show = [&](auto& f, node_ptr u, int d) {
      if (d >= depth)
        return;
      if (!u)
        return;
      std::cout << u->key() << std::endl;
      if (u->left)
        std::cout << u->left->key() << ' ';
      else
        std::cout << "--- ";
      if (u->right)
        std::cout << u->right->key() << std::endl;
      else
        std::cout << "---" << std::endl;
      f(f, u->left, d+1);
      f(f, u->right, d+1);
    };
    if (!u)
      u = _root();
    show(show, u, 0);
    std::cout<<std::endl;
  }

};

template<class T, class Compare=std::less<>>
using TreapSet = Treap<T, void, Compare>;

template<class T, class Compare=std::less<>>
using TreapMultiset = Treap<T, void, Compare, false>;

template<class T, class V, class Compare=std::less<>, bool UniqueKey=true>
class _TreapMap : public Treap<T, V, Compare, UniqueKey> {
  static_assert(!std::is_same<V, void>::value, "");
  using _base = Treap<T, V>;
 public:
  using typename _base::mapped_type;
  using reference = mapped_type&;
  reference operator[](const T& x) {
    return _base::insert({x, mapped_type()}).first->second;
  }
  reference operator[](T&& x) {
    return _base::insert({std::move(x), mapped_type()}).first->second;
  }
};

template<class T, class V, class Compare=std::less<>>
using TreapMap = _TreapMap<T, V, Compare, true>;

template<class T, class V, class Compare=std::less<>>
using TreapMultimap = _TreapMap<T, V, Compare, false>;

namespace treap {

template<class T, class Compare=std::less<>>
using set = TreapSet<T, Compare>;

template<class T, class Compare=std::less<>>
using multiset = TreapMultiset<T, Compare>;

template<class T, class V, class Compare=std::less<>>
using map = TreapMap<T, V, Compare>;

template<class T, class V, class Compare=std::less<>>
using multimap = TreapMultimap<T, V, Compare>;

} // naamespace treap
#line 2 "include/mtl/bit_manip.hpp"
#include <cstdint>
#line 4 "include/mtl/bit_manip.hpp"
#if __cplusplus >= 202002L
#ifndef MTL_CPP20
#define MTL_CPP20
#endif
#include <bit>
#endif

namespace bm {

/// Count 1s for each 8 bits
inline constexpr uint64_t popcnt_e8(uint64_t x) {
  x = (x & 0x5555555555555555) + ((x>>1) & 0x5555555555555555);
  x = (x & 0x3333333333333333) + ((x>>2) & 0x3333333333333333);
  x = (x & 0x0F0F0F0F0F0F0F0F) + ((x>>4) & 0x0F0F0F0F0F0F0F0F);
  return x;
}
/// Count 1s
inline constexpr unsigned popcnt(uint64_t x) {
#ifdef MTL_CPP20
  return std::popcount(x);
#else
  return (popcnt_e8(x) * 0x0101010101010101) >> 56;
#endif
}
/// Alias to mtl::popcnt(x)
constexpr unsigned popcount(uint64_t x) {
  return popcnt(x);
}
/// Count trailing 0s. s.t. *11011000 -> 3
inline constexpr unsigned ctz(uint64_t x) {
#ifdef MTL_CPP20
  return std::countr_zero(x);
#else
  return popcnt((x & (-x)) - 1);
#endif
}
/// Alias to mtl::ctz(x)
constexpr unsigned countr_zero(uint64_t x) {
  return ctz(x);
}
/// Count trailing 1s. s.t. *11011011 -> 2
inline constexpr unsigned cto(uint64_t x) {
#ifdef MTL_CPP20
  return std::countr_one(x);
#else
  return ctz(~x);
#endif
}
/// Alias to mtl::cto(x)
constexpr unsigned countr_one(uint64_t x) {
  return cto(x);
}
inline constexpr unsigned ctz8(uint8_t x) {
  return x == 0 ? 8 : popcnt_e8((x & (-x)) - 1);
}
/// [00..0](8bit) -> 0, [**..*](not only 0) -> 1
inline constexpr uint8_t summary(uint64_t x) {
  constexpr uint64_t hmask = 0x8080808080808080ull;
  constexpr uint64_t lmask = 0x7F7F7F7F7F7F7F7Full;
  auto a = x & hmask;
  auto b = x & lmask;
  b = hmask - b;
  b = ~b;
  auto c = (a | b) & hmask;
  c *= 0x0002040810204081ull;
  return uint8_t(c >> 56);
}
/// Extract target area of bits
inline constexpr uint64_t bextr(uint64_t x, unsigned start, unsigned len) {
  uint64_t mask = len < 64 ? (1ull<<len)-1 : 0xFFFFFFFFFFFFFFFFull;
  return (x >> start) & mask;
}
/// 00101101 -> 00111111 -count_1s-> 6
inline constexpr unsigned log2p1(uint8_t x) {
  if (x & 0x80)
    return 8;
  uint64_t p = uint64_t(x) * 0x0101010101010101ull;
  p -= 0x8040201008040201ull;
  p = ~p & 0x8080808080808080ull;
  p = (p >> 7) * 0x0101010101010101ull;
  p >>= 56;
  return p;
}
/// 00101100 -mask_mssb-> 00100000 -to_index-> 5
inline constexpr unsigned mssb8(uint8_t x) {
  assert(x != 0);
  return log2p1(x) - 1;
}
/// 00101100 -mask_lssb-> 00000100 -to_index-> 2
inline constexpr unsigned lssb8(uint8_t x) {
  assert(x != 0);
  return popcnt_e8((x & -x) - 1);
}
/// Count leading 0s. 00001011... -> 4
inline constexpr unsigned clz(uint64_t x) {
#ifdef MTL_CPP20
  return std::countl_zero(x);
#else
  if (x == 0)
    return 64;
  auto i = mssb8(summary(x));
  auto j = mssb8(bextr(x, 8 * i, 8));
  return 63 - (8 * i + j);
#endif
}
/// Alias to mtl::clz(x)
constexpr unsigned countl_zero(uint64_t x) {
  return clz(x);
}
/// Count leading 1s. 11110100... -> 4
inline constexpr unsigned clo(uint64_t x) {
#ifdef MTL_CPP20
  return std::countl_one(x);
#else
  return clz(~x);
#endif
}
/// Alias to mtl::clo(x)
constexpr unsigned countl_one(uint64_t x) {
  return clo(x);
}

inline constexpr unsigned clz8(uint8_t x) {
  return x == 0 ? 8 : 7 - mssb8(x);
}
inline constexpr uint64_t bit_reverse(uint64_t x) {
  x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
  x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
  x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
  x = ((x & 0x0F0F0F0F0F0F0F0F) << 4) | ((x & 0xF0F0F0F0F0F0F0F0) >> 4);
  x = ((x & 0x3333333333333333) << 2) | ((x & 0xCCCCCCCCCCCCCCCC) >> 2);
  x = ((x & 0x5555555555555555) << 1) | ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
  return x;
}

/// Check if x is power of 2. 00100000 -> true, 00100001 -> false
constexpr bool has_single_bit(uint64_t x) noexcept {
#ifdef MTL_CPP20
  return std::has_single_bit(x);
#else
  return x != 0 && (x & (x - 1)) == 0;
#endif
}

/// Bit width needs to represent x. 00110110 -> 6
constexpr int bit_width(uint64_t x) noexcept {
#ifdef MTL_CPP20
  return std::bit_width(x);
#else
  return 64 - clz(x);
#endif
}

/// Ceil power of 2. 00110110 -> 01000000
constexpr uint64_t bit_ceil(uint64_t x) {
#ifdef MTL_CPP20
  return std::bit_ceil(x);
#else
  if (x == 0) return 1;
  return 1ull << bit_width(x - 1);
#endif
}

/// Floor power of 2. 00110110 -> 00100000
constexpr uint64_t bit_floor(uint64_t x) {
#ifdef MTL_CPP20
  return std::bit_floor(x);
#else
  if (x == 0) return 0;
  return 1ull << (bit_width(x) - 1);
#endif
}

} // namespace bm
#line 6 "include/mtl/integer_set.hpp"
#include <array>
#include <unordered_map>
#include <initializer_list>
#line 10 "include/mtl/integer_set.hpp"

template<typename T, unsigned BITS = 64>
class 
[[deprecated("XFastTrie is expected to be used by YFastTrie. Single XFastTrie is inefficient for memory.")]]
_XFastTrie {
 public:
  using U = uint64_t;
  static constexpr int W = BITS;
  class iterator;
  static constexpr bool kKeyOnly = std::is_same<T, void>::value;
  using element_type = typename std::conditional<kKeyOnly, U, std::pair<U, T>>::type;
 private:
  struct Node;
  using node_ptr = std::shared_ptr<Node>;
  using node_weak = std::weak_ptr<Node>;
  struct Node {
    // common
    uint8_t cmask;
    std::array<node_ptr, 2> child;
    node_weak parent;
    // leaf
    element_type* vptr;
    Node() : cmask(0), child({nullptr, nullptr}), vptr(nullptr) {}
    U key() const {
      if constexpr (kKeyOnly)
        return *vptr;
      else
        return vptr->first;
    }
  };
 private:
  using _hash_table = std::unordered_map<U, node_ptr>;
  node_ptr root_, sentinel_;
  size_t size_;
  std::array<_hash_table, W+1> xmap_;

 public:
  _XFastTrie()
      : root_(std::make_shared<Node>()), sentinel_(std::make_shared<Node>()), size_(0)
  {
    sentinel_->child[0] = sentinel_->child[1] = root_->child[0] = root_->child[1] = sentinel_;
    xmap_[0].emplace(0, root_);
  }
  template<typename It>
  explicit _XFastTrie(It begin, It end) : _XFastTrie() {
    insert(begin, end);
  }
  _XFastTrie(std::initializer_list<element_type> list) : _XFastTrie(list.begin(), list.end()) {}
 private:
  void _del_node(node_ptr u) {
    u->parent.reset();
    for (int i = 0; i < 2; i++) {
      if (u->cmask & (1<<i) and u->child[i] != u) {
        _del_node(u->child[i]);
      }
      u->child[i] = nullptr;
    }
    if (u->vptr) {
      delete u->vptr;
    }
  }
  void _del() {
    if (root_)
      _del_node(root_);
    if (sentinel_)
      sentinel_->child[0] = sentinel_->child[1] = nullptr;
  }
 public:
//  TODO: Optimal copy implementation
  _XFastTrie(const _XFastTrie& r) : _XFastTrie(r.begin(), r.end()) {}
  _XFastTrie& operator=(const _XFastTrie& r) {
    _del();
    root_ = std::make_shared<Node>();
    sentinel_ = std::make_shared<Node>();
    size_ = 0;
    sentinel_->child[0] = sentinel_->child[1] =
        root_->child[0] = root_->child[1] = sentinel_;
    xmap_[0].emplace(0, root_);
    insert(r.begin(), r.end());
    return *this;
  }
  _XFastTrie(_XFastTrie&& r)
    : root_(std::move(r.root_)), sentinel_(std::move(r.sentinel_)),
      size_(std::move(r.size_)), xmap_(std::move(r.xmap_)) {}
  _XFastTrie& operator=(_XFastTrie&& r) noexcept {
    _del();
    root_ = std::move(r.root_);
    sentinel_ = std::move(r.sentinel_);
    size_ = std::move(r.size_);
    xmap_ = std::move(r.xmap_);
    return *this;
  }
  ~_XFastTrie() {
    _del();
  }

  size_t size() const { return size_; }
  bool empty() const { return size() == 0; }
  void clear() {
    *this = _XFastTrie();
  }

  iterator find(U x) const {
    auto it = xmap_[W].find(x);
    return it != xmap_[W].end() ? iterator(it->second) : end();
  }
  size_t count(U x) const { return (size_t) (find(x) != end()); }
  bool contains(U x) const { return (bool) count(x); }
  iterator lower_bound(U x) const {
    int l = 0, r = W+1;
    auto u = root_;
    while (l+1<r) {
      int c = (l+r)/2;
      auto vit = xmap_[c].find(x >> (W-c));
      if (vit != xmap_[c].end()) {
        u = vit->second;
        l = c;
      } else {
        r = c;
      }
    }
    if (l == W) return iterator(u);
    auto next = ((x>>(W-1-l))&1) == 0 ? u->child[0] : u->child[1]->child[1];
    return iterator(next);
  }
  iterator upper_bound(U x) const {
    auto it = lower_bound(x);
    return (it != end() and it.ptr_->key() == x) ? ++it : it;
  }
  iterator successor(U x) const {
    return upper_bound(x);
  }
  iterator predecessor(U x) const {
    auto it = lower_bound(x);
    return it != begin() ? --it : end();
  }

 private:
  U _key_of_elm(element_type& e) const {
    if constexpr (kKeyOnly)
      return e;
    else
      return e.first;
  }
  U _key_of(iterator it) const {
    return _key_of_elm(*(it.ptr_->vptr));
  }
  template<typename... Args>
  U _key_of_elm_args(U x, Args&&...) const { return x; }
  iterator _insert_subtree(int depth, node_ptr u, U x, element_type* eptr) {
    int i = depth;
    int c = (x >> (W-i-1)) & 1;
    auto pred = c == 1 ? u->child[1] : u->child[0]->child[0];
    assert(pred);
    for (; i < W; i++) {
      c = (x >> (W-1-i)) & 1;
      u->cmask |= 1u<<c;
      u->child[c] = std::make_shared<Node>();
      u->child[c]->parent = u;
      u = u->child[c];
      xmap_[i+1].emplace(x>>(W-1-i), u);
    }
    u->vptr = eptr;
    u->child[0] = pred;
    u->child[1] = pred->child[1];
    pred->child[1]->child[0] = u;
    pred->child[1] = u;
    auto v = u->parent.lock();
    for (i = W-1; i >= 0; i--) {
      assert(v);
      c = (x >> (W-1-i)) & 1;
      int ic = c^1;
      if ((v->cmask & (1u<<ic)) == 0
          and (!v->child[ic] or v->child[ic] == sentinel_
              or (ic == 0 ? v->child[ic]->key() > x
                          : v->child[ic]->key() < x)))
        v->child[ic] = u;
      assert(v->child[0] and v->child[1]);
      v = v->parent.lock();
    }
    size_++;
    return iterator(u);
  }
  iterator _insert(U x, element_type* eptr) {
    auto u = root_;
    int i, c;
    for (i = 0; i < W; i++) {
      c = (x >> (W-1-i)) & 1;
      if ((u->cmask & (1u<<c)) == 0) break;
      u = u->child[c];
    }
    if (i == W) return iterator(u);
    return _insert_subtree(i, u, x, eptr);
  }
  iterator _insert_hint(iterator hint, U x, element_type* eptr) {
    // Check hint isn't malicious.
    U lx=0, rx=0;
    if ((hint != begin() and x < (lx = _key_of(std::prev(hint)))) or
        (hint != end() and (rx = _key_of(hint)) < x))
      return _insert(x, eptr);
    // Find longest common path on the trie.
    int d = 0;
    if (hint != begin())
      d = std::max(d, (int) bm::clz(x ^ lx) - (64-W));
    if (hint != end())
      d = std::max(d, (int) bm::clz(x ^ rx) - (64-W));
    if (d == W) return iterator(xmap_[W][x]);
    return _insert_subtree(d, xmap_[d][x >> (W-d)], x, eptr);
  }
 public:
  iterator insert(const element_type& e) {
    return _insert(_key_of_elm(e),
                   new element_type(e));
  }
  iterator insert(element_type&& e) {
    return _insert(_key_of_elm(e),
                   new element_type(std::move(e)));
  }
  template<typename... Args>
  iterator emplace(Args&&... args) {
    return _insert(_key_of_elm_args(args...),
                   new element_type(std::forward<Args>(args)...));
  }
  template<typename... Args>
  iterator emplace_hint(iterator hint, Args&&... args) {
    return _insert_hint(hint,
                        _key_of_elm_args(args...),
                        new element_type(std::forward<Args>(args)...));
  }
  template<typename It>
  void insert(It begin, It end) {
    using traits = std::iterator_traits<It>;
    static_assert(std::is_convertible<typename traits::value_type, element_type>::value, "");
    static_assert(std::is_base_of<std::forward_iterator_tag, typename traits::iterator_category>::value, "");
    for (auto it = begin; it != end; ++it)
      insert(*it);
  }
  void insert(std::initializer_list<element_type> list) {
    insert(list.begin(), list.end());
  }
  iterator erase(iterator it) {
    if (it == end())
      return it;
    auto u = it.ptr_;
    U x = u->key();
    delete u->vptr;
    auto next = u->child[0];
    u->child[0]->child[1] = u->child[1];
    u->child[1]->child[0] = u->child[0];
    auto v = u;
    int i, c;
    for (i = W-1; i >= 0; i--) {
      c = (x >> (W-1-i)) & 1;
      auto p = v->parent.lock();
      v->parent.reset();
      p->cmask ^= 1u<<c;
      p->child[c] = nullptr;
      assert(xmap_[i+1].find(x>>(W-1-i))->second == v);
      xmap_[i+1].erase(x>>(W-1-i));
      v = p;
      if ((p->cmask & (1u<<(c^1))) != 0) break;
    }
    if (i >= 0) {
      c = (x >> (W-1-i)) & 1;
      v->child[c] = u->child[c^1];
      v = v->parent.lock();
      i--;
      for (; i >= 0; i--) {
        c = (x >> (W-1-i)) & 1;
        int ic = c^1;
        if (v->child[ic] == u) {
          v->child[ic] = u->child[c];
        }
        v = v->parent.lock();
      }
    }
    size_--;
    return iterator(next);
  }
  iterator erase(U x) {
    auto it = lower_bound(x);
    if (it.key() != x)
      return it;
    return erase(it);
  }

 public:
  class iterator {
   public:
    using value_type = element_type;
    using pointer = element_type*;
    using reference = const element_type&;
    using difference_type = long long;
    using iterator_category = std::bidirectional_iterator_tag;
   private:
    node_ptr ptr_;
    friend class _XFastTrie;
   public:
    explicit iterator(node_ptr ptr) : ptr_(ptr) {}
    reference operator*() const { return *(ptr_->vptr); }
    pointer operator->() const { return ptr_->vptr; }
    bool operator==(const iterator& r) const { return ptr_ == r.ptr_; }
    bool operator!=(const iterator& r) const { return ptr_ != r.ptr_; }
    iterator& operator++() {
      ptr_ = ptr_->child[1];
      return *this;
    }
    iterator operator++(int) {
      iterator ret = *this;
      ++*this;
      return ret;
    }
    iterator& operator--() {
      ptr_ = ptr_->child[0];
      return *this;
    }
    iterator operator--(int) {
      iterator ret = *this;
      --*this;
      return ret;
    }
    U key() const { return ptr_->key(); }
  };
  iterator begin() const { return iterator(sentinel_->child[1]); }
  iterator end() const { return iterator(sentinel_); }
};
template<typename T, unsigned BITS>
constexpr int _XFastTrie<T, BITS>::W;
template<typename T, unsigned BITS>
constexpr bool _XFastTrie<T, BITS>::kKeyOnly;
template<unsigned BITS = 64>
using XFastTrieSet = _XFastTrie<void, BITS>;
template<typename T, unsigned BITS = 64>
using XFastTrieMap = _XFastTrie<T, BITS>;


template<typename T, unsigned BITS=64>
class YFastTrie {
 public:
  using U = uint64_t;
  static constexpr int W = BITS;
  static constexpr U MAX_KEY = W == 64 ? ~uint64_t(0) : (1ull<<W)-1;
  static constexpr bool kKeyOnly = std::is_same<T, void>::value;
  using element_type = typename std::conditional<kKeyOnly, U, std::pair<U,T>>::type;
  using value_type = typename std::conditional<kKeyOnly, U, T>::type;
  using _set = typename std::conditional<kKeyOnly, TreapSet<U>, TreapMap<U,T>>::type;
  using _set_iterator = typename _set::iterator;
  using _xft = XFastTrieMap<_set, W>;
  class iterator;
 private:
  _xft xft_;
  size_t size_;

  bool _pibot_selected() {
    return rand() % W == 0;
  }
  U _key_of_elm(const element_type& e) const {
    if constexpr (kKeyOnly)
      return e;
    else
      return e.first;
  }
  U _key_of_elm(element_type&& e) const {
    if constexpr (kKeyOnly)
      return e;
    else
      return e.first;
  }
  template<typename... Args>
  U _key_of_elm_args(U x, Args&&...) const {
    return x;
  }
  U _key_of_sub(_set_iterator it) const {
    return _key_of_elm(*it);
  }
  U _key_of(iterator it) const {
    return _key_of_sub(it.sit_);
  }

 public:
  YFastTrie() : size_(0) {
    xft_.emplace(MAX_KEY, _set{});
  }
  template<typename It>
  explicit YFastTrie(It begin, It end) : YFastTrie() {
    insert(begin, end);
  }
  YFastTrie(std::initializer_list<element_type> list) : YFastTrie(list.begin(), list.end()) {}

  size_t size() const { return size_; }
  bool empty() const { return size() == 0; }
  void clear() {
    *this = YFastTrie();
  }

  iterator find(U x) const {
    auto xit = xft_.lower_bound(x);
    assert(xit != xft_.end());
    auto& s = xit->second;
    auto sit = s.find(x);
    return sit != s.end() ? iterator(this, xit, sit) : end();
  }
  size_t count(U x) const { return (size_t) (find(x) != end()); }
  bool contains(U x) const { return (bool) count(x); }
  iterator lower_bound(U x) const {
    auto xit = xft_.lower_bound(x);
    assert(xit != xft_.end());
    auto& s = xit->second;
    auto sit = s.lower_bound(x);
    if (sit == s.end()) {
      assert(std::next(xit) == xft_.end());
      return end();
    }
    return iterator(this, xit, sit);
  }
  iterator upper_bound(U x) const {
    auto it = lower_bound(x);
    return (it != end() and _key_of(it) == x) ? ++it : it;
  }
  iterator successor(U x) const {
    return upper_bound(x);
  }
  iterator predecessor(U x) const {
    auto it = lower_bound(x);
    return it != begin() ? --it : end();
  }

 private:
  template<typename C>
  iterator _insert_before(typename _xft::iterator xit, _set_iterator sit, U x, C elm_constructor) {
    auto& s = xit->second;
    // Expect 'sit = s.emplace_hint(sit, element)'
    sit = elm_constructor(s, sit);
    size_++;
    if (_pibot_selected()) {
      xit = xft_.emplace_hint(xit, x, _set());
      xit->second = s.split(std::next(sit));
    }
    return iterator(this, xit, sit);
  }
  template<typename C>
  iterator _insert(U x, C elm_constructor) {
    auto xit = xft_.lower_bound(x);
    assert(xit != xft_.end());
    auto& s = xit->second;
    auto sit = s.lower_bound(x);
    if (sit == s.end() or _key_of_sub(sit) > x) {
      return _insert_before(xit, sit, x, elm_constructor);
    }
    return iterator(this, xit, sit);
  }
  template<typename C>
  iterator _insert_hint(iterator hint, U x, C elm_constructor) {
    // Check hint isn't malicious.
    if ((hint != begin() and x <= _key_of(std::prev(hint))) or
        (hint != end() and _key_of(hint) <= x))
      return _insert(x, elm_constructor);

    auto xit = hint.xit_;
    assert(xit != xft_.end());
    auto sit = hint.sit_;
    assert(sit == xit->second.end() or _key_of_sub(sit) > x);
    return _insert_before(xit, sit, x, elm_constructor);
  }
 public:
  iterator insert(const element_type& e) {
    return _insert(_key_of_elm(e),
                   [&e]
                   (_set& s, const _set_iterator& it) {
                     return s.emplace_hint(it, e);
                   });
  }
  iterator insert(element_type&& e) {
    return _insert(_key_of_elm(e),
                   [e=std::move(e)](_set& s, const _set_iterator& it) {
                     return s.emplace_hint(it, std::move(e));
                   });
  }
  template<typename... Args>
  iterator emplace(Args&&... args) {
    return _insert(_key_of_elm_args(args...),
                   [&args...](_set& s, const _set_iterator& it) {
                     return s.emplace_hint(it, std::forward<Args>(args)...);
                   });
  }
  template<typename... Args>
  iterator emplace_hint(iterator hint, Args&&... args) {
    return _insert_hint(hint,
                        _key_of_elm_args(args...),
                        [&args...](_set& s, const _set_iterator& it) {
                          return s.emplace_hint(it, std::forward<Args>(args)...);
                        });
  }
  template<typename It>
  void insert(It begin, It end) {
    using traits = std::iterator_traits<It>;
    static_assert(std::is_convertible<typename traits::value_type, element_type>::value, "");
    static_assert(std::is_base_of<std::forward_iterator_tag, typename traits::iterator_category>::value, "");
    for (auto it = begin; it != end; ++it)
      insert(*it);
  }
  void insert(std::initializer_list<element_type> list) {
    insert(list.begin(), list.end());
  }
  iterator erase(iterator it) {
    if (it == end())
      return it;
    U x = _key_of(it);
    auto xit = it.xit_;
    assert(xit != xft_.end());
    auto& s = xit->second;
    auto sit = it.sit_;
    size_--;
    sit = s.erase(sit);
    if (x == xit.key()) {
      if (x != MAX_KEY) {
        if (!s.empty()) {
          auto& snext = std::next(xit)->second;
          sit = snext.absorb(&s);
        }
        xit = xft_.erase(xit);
      } else {
        return end();
      }
    }
    return iterator(this, xit, sit);
  }
  iterator erase(U x) {
    auto it = lower_bound(x);
    return (_key_of(it) == x) ? erase(it) : it;
  }

 public:
  class iterator {
   public:
    using value_type = element_type;
    using pointer = element_type*;
    using reference = const element_type&;
    using difference_type = long long;
    using iterator_category = std::bidirectional_iterator_tag;
    using xiterator = typename _xft::iterator;
    using siterator = _set_iterator;
   private:
    const YFastTrie* yft_;
    xiterator xit_;
    siterator sit_;
    friend class YFastTrie;
   public:
    iterator(const YFastTrie* yft, xiterator xit, siterator sit) : yft_(yft), xit_(xit), sit_(sit) {}
    reference operator*() const { return *sit_; }
    pointer operator->() const { return &*sit_; }
    bool operator==(const iterator& r) { return sit_ == r.sit_; }
    bool operator!=(const iterator& r) { return sit_ != r.sit_; }
    iterator& operator++() {
      if (++sit_ == xit_->second.end()) {
        auto nxt = std::next(xit_);
        if (nxt != yft_->xft_.end()) {
          xit_ = nxt;
          sit_ = xit_->second.begin();
        }
      }
      return *this;
    }
    iterator operator++(int) {
      iterator ret = *this;
      ++this;
      return ret;
    }
    iterator& operator--() {
      if (sit_ == xit_->second.begin()) {
        --xit_;
        sit_ = std::prev(xit_->second.end());
      } else {
        --sit_;
      }
      return *this;
    }
    iterator operator--(int) {
      iterator ret = *this;
      --this;
      return ret;
    }
  };
  iterator begin() const {
    auto xit = xft_.begin();
    return iterator(this, xit, xit->second.begin());
  }
  iterator end() const {
    auto xit = std::prev(xft_.end());
    return iterator(this, xit, xit->second.end());
  }
};
template<typename T, unsigned BITS>
constexpr int YFastTrie<T, BITS>::W;
template<typename T, unsigned BITS>
constexpr typename YFastTrie<T, BITS>::U YFastTrie<T, BITS>::MAX_KEY;
template<typename T, unsigned BITS>
constexpr bool YFastTrie<T, BITS>::kKeyOnly;
template<unsigned BITS=64>
using YFastTrieSet = YFastTrie<void, BITS>;


template<typename T, unsigned BITS=64>
class YFastTrieMAP : public YFastTrie<T, BITS> {
  using _base = YFastTrie<T, BITS>;
 public:
  using typename _base::value_type;
  using typename _base::U;
  using _base::kKeyOnly;
  using reference = value_type&;
  reference operator[](U x) {
    auto it = find(x);
    if (it == _base::end())
      it = emplace(x);
    if constexpr (kKeyOnly)
      return *it;
    else
      return it->second;
  }
};
#line 2 "test/standalone/set_test.hpp"
#include <vector>
#include <algorithm>
#include <type_traits>
#line 6 "test/standalone/set_test.hpp"
#include <set>

namespace mtl {

using std::cout;
using std::cerr;
using std::endl;

template<class Map>
void map_emplace_test() {
  using key_type = typename Map::key_type;
  using mapped_type = typename Map::mapped_type;
  Map s;
  s.emplace(std::make_pair(key_type(), mapped_type()));
  s.emplace(key_type(), mapped_type());
}

template<class Set, int Max = (int)4e5, bool Shuffle = true>
void integer_set_test() {
  std::vector<int> values;
  while (values.empty()) {
    for (int i = 0; i < Max; i++)
      if (rand()%4 == 0)
        values.push_back(i);
  }
  int n = values.size();
  auto insertions = values;
  if constexpr (Shuffle)
    std::random_shuffle(insertions.begin(), insertions.end());

  Set S(insertions.begin(), insertions.end());

  if (values != std::vector<int>(S.begin(), S.end())) {
    cout << "after insert order broken" << endl;
    exit(EXIT_FAILURE);
  }

//  S.print_for_debug();
  int target = -1;
  int pred = -1;
  int succ = values[0];
  int k = 0;
  auto log = [&]() {
    std::cout << pred << ' ' << target << ' ' << succ << std::endl;
  };
  for (int i = 0; i < Max; i++) {
    if (k < n and values[k] == i) {
      target = values[k];
      pred = k-1 >= 0 ? values[k-1] : -1;
      succ = k+1 < n ? values[k+1] : -1;
      k++;
    } else {
      pred = k-1 >= 0 ? values[k-1] : -1;
      target = -1;
    }

    auto fit = S.find(i);
    if (fit != S.end()) {
      if ((int)*fit != i) {
        std::cout << "find: " << i << std::endl;
        log();
        exit(EXIT_FAILURE);
      }
    } else {
      if (target != -1) {
        log();
        exit(EXIT_FAILURE);
      }
    }

    auto sucit = S.upper_bound(i);
    if (sucit != S.end()) {
      if ((int)*sucit != succ) {
        std::cout << "succ: " << *sucit << std::endl;
        log();
        exit(EXIT_FAILURE);
      }
    } else {
      if (succ != -1) {
        log();
        exit(EXIT_FAILURE);
      }
    }

    auto predit = S.lower_bound(i);
    if (predit != S.begin()) {
      --predit;
      if ((int)*predit != pred) {
        std::cout << "pred: " << *predit << std::endl;
        log();
        exit(EXIT_FAILURE);
      }
    } else {
      if (pred != -1) {
        log();
        exit(EXIT_FAILURE);
      }
    }
  }

  int size = n;
  if ((int) S.size() != size) {
    std::cout << S.size() << ' ' << size<< std::endl;
    log();
    exit(EXIT_FAILURE);
  }

  for (int v : insertions) {
    auto f = S.find(v);
    assert(f != S.end());
    auto p = f;
    auto m = std::next(f);
    for (int i = 0; i < 2 and p != S.begin(); i++)
      --p;
    for (int i = 0; i < 2 and m != S.end(); i++)
      ++m;
    std::vector<unsigned> o(p,m);
    o.erase(find(o.begin(), o.end(), v));
    S.erase(v);
    size--;

    {
      auto lb = S.lower_bound(v);
      auto p = lb, m = lb;
      for (int i = 0; i < 2 and p != S.begin(); i++)
        --p;
      for (int i = 0; i < 2 and m != S.end(); i++)
        ++m;
      if (o != std::vector<unsigned>(p,m)) {
        std::cout << n-size<<" after erase "<<v<<" order broken " << endl;
        for (auto v:o)
          cerr<<v<<' ';
        cerr<<endl;
        for (auto it = p; it != m; ++it) {
          cerr<<*it<<' ';
        }
        cerr<<endl;
        exit(EXIT_FAILURE);
      }
    }
    if ((int) S.size() != size) {
      std::cout << S.size() << ' ' << size<< std::endl;
      exit(EXIT_FAILURE);
    }
  }
  cerr<<"integer_set_test ok"<<endl;
}

}
#line 4 "test/standalone/integer_set_test.cpp"

constexpr int W = 20;
//constexpr int Max = 4e5;
//
//template<typename Set>
//int test_set() {
//  std::vector<int> values;
//  while (values.empty()) {
//    for (int i = 0; i < Max; i++) {
//      if (i == 0 or rand()%4 == 0)
//        values.push_back(i);
//    }
//  }
//  int n = values.size();
//  std::vector<int> shuffled = values;
//  for (int i = 0; i < n; i++) {
//    std::swap(shuffled[i], shuffled[rand()%n]);
//  }
//
//  Set S;
//  for (int v : shuffled) {
//    S.insert(v);
//  }
////  S.print_for_debug();
//  int target = -1;
//  int pred = -1;
//  int succ = values[0];
//  int k = 0;
//  auto log = [&]() {
//    std::cout << pred << ' ' << target << ' ' << succ << std::endl;
//    assert(false);
//  };
//  for (int i = 0; i < Max; i++) {
//    if (k < n and values[k] == i) {
//      target = values[k];
//      pred = k-1 >= 0 ? values[k-1] : -1;
//      succ = k+1 < n ? values[k+1] : -1;
//      k++;
//    } else {
//      pred = k-1 >= 0 ? values[k-1] : -1;
//      target = -1;
//    }
//
//    auto fit = S.find(i);
//    if (fit != S.end()) {
//      if ((int) *fit != i) {
//        std::cout << "find: " << i << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (target != -1) {
//        log();
//        return 1;
//      }
//    }
//
//    auto sucit = S.successor(i);
//    if (sucit != S.end()) {
//      if ((int) *sucit != succ) {
//        std::cout << "succ: " << *sucit << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (succ != -1) {
//        log();
//        return 1;
//      }
//    }
//
//    auto predit = S.predecessor(i);
//    if (predit != S.end()) {
//      if ((int) *predit != pred) {
//        std::cout << "pred: " << *predit << std::endl;
//        log();
//        return 1;
//      }
//    } else {
//      if (pred != -1) {
//        log();
//        return 1;
//      }
//    }
//  }
//
//  int size = n;
//  if ((int) S.size() != size) {
//    std::cout << S.size() << ' ' << size<< std::endl;
//    log();
//    return 1;
//  }
//  for (int v : shuffled) {
//    S.erase(v);
//    size--;
//    if ((int) S.size() != size) {
//      std::cout << S.size() << ' ' << size<< std::endl;
//      assert(false);
//      return 1;
//    }
//  }
//  return 0;
//}

int main() {
//  mtl::integer_set_test<XFastTrieSet<W>>();
//  mtl::integer_set_test<YFastTrieSet<W>>();
  std::cout << "OK" << std::endl;
}
Back to top page