Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Priority Queue

A priority queue is a data structure which maintains a set $S$ of elements, each of with an associated value (key), and supports the following operations:

$insert(S, k)$: insert an element $k$ into the set $S$

$extractMax(S)$: remove and return the element of $S$ with the largest key

Write a program which performs the $insert(S, k)$ and $extractMax(S)$ operations to a priority queue $S$.
The priority queue manages a set of integers, which are also keys for the priority.

Input

Multiple operations to the priority queue $S$ are given. Each operation is given by "insert $k$", "extract" or "end" in a line. Here, $k$ represents an integer element to be inserted to the priority queue.

The input ends with "end" operation.

Output

For each "extract" operation, print the element extracted from the priority queue $S$ in a line.

Constraints

The number of operations $\leq 2,000,000$

$0 \leq k \leq 2,000,000,000$

Sample Input 1

insert 8
insert 2
extract
insert 10
extract
insert 11
extract
extract
end

Sample Output 1

8
10
11
2

Solution in Scala (judge verdict: Accepted)

import scala.io.StdIn.readLine;
import scala.reflect.ClassTag;
object Main {
    def main(args: Array[String]): Unit = {
        def c(a: Long, b: Long): Int = if (a < b) -1 else if (a > b) 1 else 0;
        val h = Heap[Long](c);
        sub(h)
    }
    def sub(heap: Heap[Long]): Unit = {
        readLine.split(" ") match {
            case Array("insert", key) =>
                heap.insert(key.toLong);
                sub(heap);
            case Array("extract") => 
                println(heap.extract.getOrElse(-1L));
                sub(heap);
            case Array("end") => ()
        }
    }
}

class Heap[A](size: Int, compare: (A, A) => Int)(implicit m: ClassTag[Option[A]]) {
    var tree: Array[Option[A]] = m.newArray(size).map(a => None);
    var cnt = 0;
    
    def insert(key: A): Unit = {
        def _insert(currPtr: Int): Unit = {
            if (currPtr > 0) {
                // currPtr が奇数の場合は左側の子, 偶数の場合は右側の子
                val parentPtr = if (currPtr % 2 != 0) (currPtr - 1) / 2 else  (currPtr - 2) / 2;
                if (compare(tree(currPtr).get, tree(parentPtr).get) > 0) {
                    swap(currPtr, parentPtr);
                    _insert(parentPtr);
                }
            }
        }
        if (cnt < size) {
            tree(cnt) = Option(key);
            _insert(cnt);
            cnt += 1;
        }
        
    }
    def extract(): Option[A] = {
        if (cnt > 0) {
            val top = tree(0);
            if (cnt == 1) {
                tree(0) = None;
            } else {
                tree(0) = tree(cnt - 1);
                tree(cnt - 1) = None;
                heapify(0);
            }
            cnt -= 1;
            top;
        } else {
            None;
        }
    }
    
    def heapify(currPtr: Int): Unit = {
        if (currPtr < size && tree(currPtr) != None) {
            val leftPtr = currPtr * 2 + 1;
            val rightPtr = currPtr * 2 + 2;
            val curr = tree(currPtr);
            val left = if (leftPtr < size) tree(leftPtr) else None;
            val right = if (rightPtr < size) tree(rightPtr) else None;
            if (right != None) { // 両方の子ノードが存在する
                val swapPtr = if (compare(left.get, right.get) < 0) rightPtr else leftPtr;
                if (compare(curr.get, tree(swapPtr).get) < 0) {
                    swap(currPtr, swapPtr);
                    heapify(swapPtr);
                }
            } else if (left != None) { // 左の子ノードのみ存在する
                if (compare(curr.get, left.get) < 0) {
                    swap(currPtr, leftPtr);
                    heapify(leftPtr);
                }
            }
        }
    }
    
    def swap (ptrA: Int, ptrB: Int): Unit = {
        val tmp = tree(ptrA);
        tree(ptrA) = tree(ptrB);
        tree(ptrB) = tmp;
    }
    
}
object Heap {
    def apply[A](compare: (A, A) => Int): Heap[A] = {
        new Heap[A](2000000, compare);
    }
}