$\newcommand{\O}{\mathrm{O}}$
元論文は "Melding priority queues" [Mendelson, Tarjan, Thorup, Zwick 2004].
時間計算量: insert, meld ならし $\O (1)$, find_min $\O (1)$, erase ならし $\O \left( pq(n) \alpha(n, n / pq(n)) \right)$
(元のヒープが insert, delete, find_min を $pq(n)\ (= \O (\log n))$ time で処理する場合)
// BaseHeap が与えられる non meldable heap に対応 // multiset を non meldable ヒープとして使った場合について実装している template<typename _Key, class _Compare=less<_Key> > class BaseHeap { private: multiset<_Key, _Compare> heap; public: BaseHeap(){} bool empty() const { return heap.empty(); } void insert(const _Key& key){ heap.insert(key); } void erase(const _Key& key){ heap.erase(heap.find(key)); } const _Key& find_min() const { return *heap.begin(); } }; template<typename _Key, class _Compare=less<_Key> > class MeldableHeapNode { private: BaseHeap<_Key, _Compare> bheap; MeldableHeapNode *par; unsigned int rank; public: MeldableHeapNode(const _Key& key) : par(this), rank(0u){ bheap.insert(key); } bool empty() const { return bheap.empty(); } MeldableHeapNode*& get_parent(){ return par; } MeldableHeapNode*& get_grandparent(){ return par->get_parent(); } unsigned int& get_rank(){ return rank; } bool is_root() const { return this == par; } void insert(const _Key& key){ bheap.insert(key); } void erase(const _Key& key){ bheap.erase(key); } const _Key& find_min() const { return bheap.find_min(); } }; template<typename _Key, class _Compare=less<_Key> > class MeldableHeaps { private: stack<MeldableHeapNode<_Key, _Compare>*> free_pointer; void cut_path(MeldableHeapNode<_Key, _Compare> *cur_heap){ if(!cur_heap->is_root()){ cut_path(cur_heap->get_parent()); unhang(cur_heap, cur_heap->get_parent()); } } void compress_path(MeldableHeapNode<_Key, _Compare> *cur_heap){ if(!cur_heap->is_root()){ compress_path(cur_heap->get_parent()); hang(cur_heap, cur_heap->get_grandparent()); } } void hang(MeldableHeapNode<_Key, _Compare> *heap1, MeldableHeapNode<_Key, _Compare> *heap2){ if(!heap1->empty()) heap2->insert(heap1->find_min()); heap1->get_parent() = heap2; } void unhang(MeldableHeapNode<_Key, _Compare> *heap1, MeldableHeapNode<_Key, _Compare> *heap2){ heap2->erase(heap1->find_min()); } public: MeldableHeaps(){} ~MeldableHeaps(){ while(!free_pointer.empty()){ MeldableHeapNode<_Key, _Compare> *heap = free_pointer.top(); free_pointer.pop(); delete heap; } } MeldableHeapNode<_Key, _Compare> *make_heap(const _Key& key){ free_pointer.push(new MeldableHeapNode<_Key, _Compare>(key)); return free_pointer.top(); } MeldableHeapNode<_Key, _Compare> *insert(MeldableHeapNode<_Key, _Compare> *heap, const _Key& key){ assert(heap->is_root()); MeldableHeapNode<_Key, _Compare> *return_heap = make_heap(key); meld(heap, return_heap); return return_heap; } void erase(MeldableHeapNode<_Key, _Compare> *key_heap, const _Key& key){ cut_path(key_heap); key_heap->erase(key); compress_path(key_heap); } const _Key& find_min(MeldableHeapNode<_Key, _Compare> *heap){ assert(heap->is_root() && !heap->empty()); return heap->find_min(); } MeldableHeapNode<_Key, _Compare> *meld(MeldableHeapNode<_Key, _Compare> *heap1, MeldableHeapNode<_Key, _Compare> *heap2){ assert(heap1->is_root() && heap2->is_root()); if(heap1->get_rank() < heap2->get_rank()) swap(heap1, heap2); hang(heap2, heap1); if(heap1->get_rank() == heap2->get_rank()) ++heap1->get_rank(); return heap1; } MeldableHeapNode<_Key, _Compare> *find_root(MeldableHeapNode<_Key, _Compare> *heap){ cut_path(heap); compress_path(heap); } };
AOJ : Minimum Spanning Tree 提出コード