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 C# (judge verdict: Accepted)

using System;
using System.Text;

namespace ALDS1_9_C_PriorityQueue
{
	class Program
	{
		static void Main ( string[] args )
		{
			PriorityQueue priorityQueue = new PriorityQueue (1500000);
			string inputStr;
			StringBuilder output = new StringBuilder (10000);

			while ((inputStr = Console.ReadLine ()) != "end")
			{
				string[] split = inputStr.Split (' ');

				if (split[0] == "insert")
				{
					priorityQueue.Insert (int.Parse (split[1]));
				}
				else
				{
					int result = priorityQueue.ExtractMax ();
					output.AppendLine (result.ToString ());
				}
			}

			Console.Write (output);
		}
	}

	class PriorityQueue
	{
		public PriorityQueue ( int capacity )
		{
			this.NumArray = new int[capacity + 1];
			this.ArrayIndex = 0;
		}

		private int[] NumArray { set; get; }
		private int ArrayIndex { set; get; }
		private const int Infty = int.MinValue;

		public void Insert ( int value )
		{
			ArrayIndex++;

			if (NumArray.Length <= ArrayIndex)
			{
				int[] tmp = new int[NumArray.Length];
				NumArray.CopyTo (tmp, 0);
				NumArray = new int[NumArray.Length + 1];
				tmp.CopyTo (NumArray, 0);
			}

			NumArray[ArrayIndex] = Infty;
			IncreaseKey (ArrayIndex, value);
		}

		public int ExtractMax ()
		{
			if (ArrayIndex < 1)
			{
				return Infty;
			}

			int max = NumArray[1];

			NumArray[1] = NumArray[ArrayIndex];
			ArrayIndex--;

			MaxHeapify (1);

			return max;
		}

		private void IncreaseKey ( int index, int value )
		{
			if (value < NumArray[index])
			{
				return;
			}

			NumArray[index] = value;

			while (1 < index && NumArray[ParentKey (index)] < NumArray[index])
			{
				int p = ParentKey (index);

				var tmp = NumArray[p];
				NumArray[p] = NumArray[index];
				NumArray[index] = tmp;

				index = p;
			}
		}

		private void MaxHeapify ( int index )
		{
			int leftIndex = LeftKey (index);
			int rightindex = RightKey (index);
			int maxIndex;

			if (leftIndex <= ArrayIndex && NumArray[index] < NumArray[leftIndex])
			{
				maxIndex = leftIndex;
			}
			else
			{
				maxIndex = index;
			}

			if (rightindex <= ArrayIndex && NumArray[maxIndex] < NumArray[rightindex])
			{
				maxIndex = rightindex;
			}

			if (maxIndex != index)
			{
				var tmp = NumArray[index];
				NumArray[index] = NumArray[maxIndex];
				NumArray[maxIndex] = tmp;

				MaxHeapify (maxIndex);
			}
		}

		private int ParentKey ( int index )
		{
			return index / 2;
		}
		private int LeftKey ( int index )
		{
			return index * 2;
		}
		private int RightKey ( int index )
		{
			return index * 2 + 1;
		}
	}
}