This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub noshi91/Library
#include "other/int_alias.cpp" #include <algorithm> #include <cstddef> #include <iterator> #include <limits> #include <memory> #include <random> #include <utility> #include <vector> template <class W> class ternary_treap { using T = typename W::value_type; public: using key_type = std::vector<T>; private: using key_itr = typename key_type::const_iterator; class node_type; using node_ptr = std::unique_ptr<node_type>; class mid_type { friend ternary_treap; usize prio_; usize key_prio; node_ptr ptr; void fix() { prio_ = std::max(key_prio, prio(ptr)); } public: mid_type() : prio_(0), key_prio(0), ptr() {} }; class node_type { friend ternary_treap; T key; node_ptr left; mid_type mid; node_ptr right; usize prio() const { return mid.prio_; } public: node_type(const T key) : key(key), left(), mid(), right() {} }; static usize rand() { static std::default_random_engine rng(91); static std::uniform_int_distribution<usize> uid( 1, std::numeric_limits<usize>::max()); return uid(rng); } static usize prio(const node_ptr &ptr) { return ptr ? ptr->prio() : 0; } static void rot_left(node_ptr &ptr) { node_ptr right = std::move(ptr->right); ptr->right = std::move(right->left); right->left = std::move(ptr); ptr = std::move(right); } static void rot_right(node_ptr &ptr) { node_ptr left = std::move(ptr->left); ptr->left = std::move(left->right); left->right = std::move(ptr); ptr = std::move(left); } static bool contains(const mid_type &mid, const key_itr f, const key_itr l) { if (f == l) return mid.key_prio != 0; return contains(mid.ptr, f, l); } static bool contains(const node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) return false; if (!W::compare(ptr->key, *f)) return contains(ptr->left, f, l); else if (!W::compare(*f, ptr->key)) return contains(ptr->right, f, l); else return contains(ptr->mid, std::next(f), l); } static void insert(mid_type &mid, const key_itr f, const key_itr l) { if (f == l) { if (mid.key_prio == 0) mid.key_prio = rand(); } else { insert(mid.ptr, f, l); } mid.fix(); } static void insert(node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) ptr = std::make_unique<node_type>(*f); if (!W::compare(ptr->key, *f)) { insert(ptr->left, f, l); if (ptr->left->prio() > ptr->prio()) rot_right(ptr); } else if (!W::compare(*f, ptr->key)) { insert(ptr->right, f, l); if (ptr->right->prio() > ptr->prio()) rot_left(ptr); } else { insert(ptr->mid, std::next(f), l); } } static void erase(mid_type &mid, const key_itr f, const key_itr l) { if (f == l) { if (mid.key_prio != 0) mid.key_prio = 0; } else { erase(mid.ptr, f, l); } mid.fix(); } static void erase(node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) return; if (!W::compare(ptr->key, *f)) { erase(ptr->left, f, l); } else if (!W::compare(*f, ptr->key)) { erase(ptr->right, f, l); } else { erase(ptr->mid, std::next(f), l); heapify(ptr); } } static void heapify(node_ptr &ptr) { if (prio(ptr->left) > ptr->prio() || prio(ptr->right) > ptr->prio()) { if (prio(ptr->left) >= prio(ptr->right)) { rot_right(ptr); heapify(ptr->right); } else { rot_left(ptr); heapify(ptr->left); } } else { if (ptr->prio() == 0) ptr.reset(); } } mid_type root; public: ternary_treap() = default; bool empty() const { return root.prio == 0; } bool contains(const key_type x) const { return contains(root, x.cbegin(), x.cend()); } void insert(const std::vector<T> x) { insert(root, x.cbegin(), x.cend()); } void erase(const std::vector<T> x) { erase(root, x.cbegin(), x.cend()); } }; /** * @brief Ternary Treap * @see https://scrapbox.io/data-structures/Ternary_Search_Tree */
#line 2 "other/int_alias.cpp" #include <cstddef> #include <cstdint> using i32 = std::int32_t; using i64 = std::int64_t; using u32 = std::uint32_t; using u64 = std::uint64_t; using isize = std::ptrdiff_t; using usize = std::size_t; #line 2 "data_structure/ternary_treap.cpp" #include <algorithm> #line 5 "data_structure/ternary_treap.cpp" #include <iterator> #include <limits> #include <memory> #include <random> #include <utility> #include <vector> template <class W> class ternary_treap { using T = typename W::value_type; public: using key_type = std::vector<T>; private: using key_itr = typename key_type::const_iterator; class node_type; using node_ptr = std::unique_ptr<node_type>; class mid_type { friend ternary_treap; usize prio_; usize key_prio; node_ptr ptr; void fix() { prio_ = std::max(key_prio, prio(ptr)); } public: mid_type() : prio_(0), key_prio(0), ptr() {} }; class node_type { friend ternary_treap; T key; node_ptr left; mid_type mid; node_ptr right; usize prio() const { return mid.prio_; } public: node_type(const T key) : key(key), left(), mid(), right() {} }; static usize rand() { static std::default_random_engine rng(91); static std::uniform_int_distribution<usize> uid( 1, std::numeric_limits<usize>::max()); return uid(rng); } static usize prio(const node_ptr &ptr) { return ptr ? ptr->prio() : 0; } static void rot_left(node_ptr &ptr) { node_ptr right = std::move(ptr->right); ptr->right = std::move(right->left); right->left = std::move(ptr); ptr = std::move(right); } static void rot_right(node_ptr &ptr) { node_ptr left = std::move(ptr->left); ptr->left = std::move(left->right); left->right = std::move(ptr); ptr = std::move(left); } static bool contains(const mid_type &mid, const key_itr f, const key_itr l) { if (f == l) return mid.key_prio != 0; return contains(mid.ptr, f, l); } static bool contains(const node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) return false; if (!W::compare(ptr->key, *f)) return contains(ptr->left, f, l); else if (!W::compare(*f, ptr->key)) return contains(ptr->right, f, l); else return contains(ptr->mid, std::next(f), l); } static void insert(mid_type &mid, const key_itr f, const key_itr l) { if (f == l) { if (mid.key_prio == 0) mid.key_prio = rand(); } else { insert(mid.ptr, f, l); } mid.fix(); } static void insert(node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) ptr = std::make_unique<node_type>(*f); if (!W::compare(ptr->key, *f)) { insert(ptr->left, f, l); if (ptr->left->prio() > ptr->prio()) rot_right(ptr); } else if (!W::compare(*f, ptr->key)) { insert(ptr->right, f, l); if (ptr->right->prio() > ptr->prio()) rot_left(ptr); } else { insert(ptr->mid, std::next(f), l); } } static void erase(mid_type &mid, const key_itr f, const key_itr l) { if (f == l) { if (mid.key_prio != 0) mid.key_prio = 0; } else { erase(mid.ptr, f, l); } mid.fix(); } static void erase(node_ptr &ptr, const key_itr f, const key_itr l) { if (!ptr) return; if (!W::compare(ptr->key, *f)) { erase(ptr->left, f, l); } else if (!W::compare(*f, ptr->key)) { erase(ptr->right, f, l); } else { erase(ptr->mid, std::next(f), l); heapify(ptr); } } static void heapify(node_ptr &ptr) { if (prio(ptr->left) > ptr->prio() || prio(ptr->right) > ptr->prio()) { if (prio(ptr->left) >= prio(ptr->right)) { rot_right(ptr); heapify(ptr->right); } else { rot_left(ptr); heapify(ptr->left); } } else { if (ptr->prio() == 0) ptr.reset(); } } mid_type root; public: ternary_treap() = default; bool empty() const { return root.prio == 0; } bool contains(const key_type x) const { return contains(root, x.cbegin(), x.cend()); } void insert(const std::vector<T> x) { insert(root, x.cbegin(), x.cend()); } void erase(const std::vector<T> x) { erase(root, x.cbegin(), x.cend()); } }; /** * @brief Ternary Treap * @see https://scrapbox.io/data-structures/Ternary_Search_Tree */