namespace PriorityQ { using KeyT = UInt32; using System; using System.Collections.Generic; using System.Linq; class Tuple { // for DotNet 3.5 without Tuple's public K Item1; public V Item2; public Tuple(K k, V v) { Item1 = k; Item2 = v; } public override string ToString() { return "(" + Item1.ToString() + ", " + Item2.ToString() + ")"; } } class MinHeapPQ { private struct HeapEntry { public KeyT k; public V v; public HeapEntry(KeyT k, V v) { this.k = k; this.v = v; } } private List pq; private MinHeapPQ() { this.pq = new List(); } private bool mt { get { return pq.Count == 0; } } private int sz { get { var cnt = pq.Count; return (cnt == 0) ? 0 : cnt - 1; } } private Tuple pkmn { get { if (pq.Count == 0) return null; else { var mn = pq[0]; return new Tuple(mn.k, mn.v); } } } private void psh(KeyT k, V v) { // add extra very high item if none if (pq.Count == 0) pq.Add(new HeapEntry(UInt32.MaxValue, v)); var i = pq.Count; pq.Add(pq[i - 1]); // copy bottom item... for (var ni = i >> 1; ni > 0; i >>= 1, ni >>= 1) { var t = pq[ni - 1]; if (t.k > k) pq[i - 1] = t; else break; } pq[i - 1] = new HeapEntry(k, v); } private void siftdown(KeyT k, V v, int ndx) { var cnt = pq.Count - 1; var i = ndx; for (var ni = i + i + 1; ni < cnt; ni = ni + ni + 1) { var oi = i; var lk = pq[ni].k; var rk = pq[ni + 1].k; var nk = k; if (k > lk) { i = ni; nk = lk; } if (nk > rk) { ni += 1; i = ni; } if (i != oi) pq[oi] = pq[i]; else break; } pq[i] = new HeapEntry(k, v); } private void rplcmin(KeyT k, V v) { if (pq.Count > 1) siftdown(k, v, 0); } private void dltmin() { var lsti = pq.Count - 2; if (lsti <= 0) pq.Clear(); else { var lkv = pq[lsti]; pq.RemoveAt(lsti); siftdown(lkv.k, lkv.v, 0); } } private void reheap(int i) { var lfti = i + i + 1; if (lfti < sz) { var rghti = lfti + 1; reheap(lfti); reheap(rghti); var ckv = pq[i]; siftdown(ckv.k, ckv.v, i); } } private void bld(IEnumerable> sq) { var sqm = from e in sq select new HeapEntry(e.Item1, e.Item2); pq = sqm.ToList(); var sz = pq.Count; if (sz > 0) { var lkv = pq[sz - 1]; pq.Add(new HeapEntry(KeyT.MaxValue, lkv.v)); reheap(0); } } private IEnumerable> sq() { return from e in pq where e.k != KeyT.MaxValue select new Tuple(e.k, e.v); } private void adj(Func> f) { var cnt = pq.Count - 1; for (var i = 0; i < cnt; ++i) { var e = pq[i]; var r = f(e.k, e.v); pq[i] = new HeapEntry(r.Item1, r.Item2); } reheap(0); } public static MinHeapPQ empty { get { return new MinHeapPQ(); } } public static bool isEmpty(MinHeapPQ pq) { return pq.mt; } public static int size(MinHeapPQ pq) { return pq.sz; } public static Tuple peekMin(MinHeapPQ pq) { return pq.pkmn; } public static MinHeapPQ push(KeyT k, V v, MinHeapPQ pq) { pq.psh(k, v); return pq; } public static MinHeapPQ replaceMin(KeyT k, V v, MinHeapPQ pq) { pq.rplcmin(k, v); return pq; } public static MinHeapPQ deleteMin(MinHeapPQ pq) { pq.dltmin(); return pq; } public static MinHeapPQ merge(MinHeapPQ pq1, MinHeapPQ pq2) { return fromSeq(pq1.sq().Concat(pq2.sq())); } public static MinHeapPQ adjust(Func> f, MinHeapPQ pq) { pq.adj(f); return pq; } public static MinHeapPQ fromSeq(IEnumerable> sq) { var pq = new MinHeapPQ(); pq.bld(sq); return pq; } public static Tuple, MinHeapPQ> popMin(MinHeapPQ pq) { var rslt = pq.pkmn; if (rslt == null) return null; pq.dltmin(); return new Tuple, MinHeapPQ>(rslt, pq); } public static IEnumerable> toSeq(MinHeapPQ pq) { for (; !pq.mt; pq.dltmin()) yield return pq.pkmn; } public static IEnumerable> sort(IEnumerable> sq) { return toSeq(fromSeq(sq)); } } }