diff --git a/trees/assoc_heap.hh b/trees/assoc_heap.hh new file mode 100644 index 0000000..dce13f5 --- /dev/null +++ b/trees/assoc_heap.hh @@ -0,0 +1,73 @@ +template , + typename _T_Hash = hash<_Tp>> +class assoc_heap { +private: + template static constexpr auto __map_types(T _t) { + return make_tuple(std::priority_queue<_Tp, _Sequence, T>(_t)); + } + template static constexpr auto __map_types(T _t, U... _o) { + return tuple_cat(make_tuple(std::priority_queue<_Tp, _Sequence, T>(_t)), __map_types(_o...)); + } + + template static constexpr void __push(_Tp _val, T& _c) { + _c.push(_val); + } + + template static constexpr void __push(_Tp _val, T& _c, U&... _o) { + __push(_val, _c); + __push(_val, _o...); + } + + template class __assoc_heap { + private: + _Tc _content; + _T_CC _comp; + unordered_map<_Tp, size_t, _T_Hash> _count; + size_t _size; + + template void __roll() { + while (get(_content).size() && !_count[get(_content).top()]) { + get(_content).pop(); + } + } + public: + __assoc_heap(_Tc _content, _T_CC _comp) : + _content(_content), _comp(_comp), _size(0) {} + + template constexpr _Tp top() { + __roll(); + return get(_content).top(); + } + + template constexpr void pop() { + __roll(); + _count[get(_content).top()] -= 1; + --_size; + get(_content).pop(); + } + + constexpr void push(_Tp __val) { + _count[__val] += 1; + ++_size; + apply([&] (auto&... cs) { __push(__val, cs...); }, _content); + } + + constexpr size_t size() const { + return _size; + } + + constexpr bool empty() const { + return !_size; + } + + template constexpr void emplace(T... _val) { + push(_Tp(_val...)); + } + }; + +public: + template static auto make(tuple<_T_cs...> _comp) { + auto _container = apply([&](auto... all) { return __map_types(all...); }, _comp); + return __assoc_heap>(_container, _comp); + } +};