Problem:
ワカサギ釣り大会 2

桧原湖でワカサギ釣り大会が行われました。今回はキャッチ＆リリースが推奨されているようです。

参加者番号と釣った匹数またはリリースした匹数を１つのイベントとして順番に読み込み、各イベントの直後に最も多くのワカサギを手元に獲得している参加者番号と匹数を出力するプログラムを作成してください。最も多く獲得している参加者が複数いる場合（あるいは全ての参加者が 0 匹の場合）は、その中で参加者番号が最も小さい一人を出力してください。

入力

入力は以下の形式で与えられる。

n q
a1 v1
a2 v2
:
aq vq

n (1 ≤ n ≤ 1000000) は参加者の数、q (1 ≤ q ≤ 100000)はイベントの数を表す。ai (1 ≤ ai ≤ n)   vi ( -100 ≤ vi ≤ 100) は、i 番目のイベントで参加者 ai が vi 匹獲得あるいはリリースしたことを示す。vi は正の値が獲得、負の値がリリースを示し、0 が与えられることはない。

出力

各イベントごとに、最も多くのワカサギを手元に獲得している参加者の参加者番号と匹数を１つの空白区切りで１行に出力する。

入力例1

3 5
1 4
2 5
1 3
3 6
2 7

出力例1

1 4
2 5
1 7
1 7
2 12

入力例2

3 5
1 4
2 5
2 -3
3 4
1 -1

出力例2

1 4
2 5
1 4
1 4
3 4

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace AIZU
{
	class VT : IComparable<VT>
	{
		public int s;
		public int V;
		public VT(int a, int c) { s = a; V = c; }
		#region Compare
		public static int Sign(VT a, VT b) { return Math.Sign(a.V - b.V); }
		public int CompareTo(VT g)
		{
			if (g == null) return 1;
			if (V == g.V) return -(s.CompareTo(g.s));
			return V.CompareTo(g.V);
		}
		#endregion
	}
	class PriorityQueue<T> where T : IComparable<T>
	{
		#region FieldAndInitialize
		//http://ufcpp.net/study/algorithm/col_heap.html
		List<T> me = new List<T>();
		List<int> Member = new List<int>();
		static Func<T, T, int> Sign = (i, j) => i.CompareTo(j);
		static Func<T, int> ID = i => i.GetHashCode();
		public PriorityQueue() { }
		public PriorityQueue(Func<T, T, int> F) { Sign = F; }
		public PriorityQueue(Func<T, int> F) { ID = F; }
		#endregion
		#region Control
		static void PushHeap(
			 List<T> array, List<int> member, Func<T, int> ID, T elem)
		{
			int N = array.Count;
			array.Add(elem);  //index of last equals to N
			member.Add(ID(elem));
			Ascend(array,member,N);
		}
		static T PopHeap(List<T> array, List<int> member, Func<T, int> ID)
		{
			int N = array.Count - 1;   //last index
			T peek = array[0];
			array[0] = array[N]; //paint out root
			array.RemoveAt(N);
			member[0] = member[N];
			member.RemoveAt(N);
			Descend(array,member,0);
			return peek;
		}
		static void Ascend(List<T> array, List<int> member, int index) {
			int N = index;
			while (N != 0)
			{
				int i = (N - 1) >> 1;//i represents N's parent
				if (Sign(array[N], array[i]) > 0)
				{ //N bigger than i
					T tmp = array[N]; array[N] = array[i]; array[i] = tmp;
					int tnp = member[N]; member[N] = member[i]; member[i] = tnp;
				}//swap
				N = i;   //update
			}
		}
		static void Descend(List<T> array, List<int> member, int index) {
			int N = array.Count;
			for (int i = index, j; (j = 2 * i + 1) < N;)
			{   //j is the left child of i
				if (j != N - 1 && Sign(array[j], array[j + 1]) < 0) //not last and  inferior to next
					j++;
				if (Sign(array[i], array[j]) < 0)
				{ //i inf to j
					T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
					int tnp = member[j]; member[j] = member[i]; member[i] = tnp;
				}//swap
				i = j;
			}
		}
		static void HeapReplace(List<T> array, List<int> member, Func<T, int> ID, int index, T NEW)
		{
			bool exceling = Sign(array[index], NEW) < 0;
			array[index] = NEW;
			member[index] = ID(NEW);
			if (exceling) Ascend(array, member, index);
			else Descend(array, member, index);
		}
		#endregion
		#region Data
		public void Push(T elem) { PushHeap(me, Member, ID, elem); }
		public T Pop() { return PopHeap(me, Member, ID); }
		public T Top { get { return me[0]; } }
		public int Count { get { return me.Count; } }
		public int HeapIndex(Func<T, bool> data)
		{
			return me.FindIndex(i => data(i));
		}
		public int HeapIndex(int d) { return Member.IndexOf(d); }
		public void Gain(T NEW, int index)
		{
			HeapReplace(me, Member, ID, index, NEW);
		}
		public T Access(int t)
		{
			if (t >= me.Count) return default(T);
			else return me[t];
		}
		#endregion
	}
	class Program
	{
		#region Reserve
		static int cin() { return cin(-1); }
		static int cin(int D)
		{
			string s = Console.ReadLine();
			if (string.IsNullOrEmpty(s))
				return D;
			return int.Parse(s);
		}
		static int[] cins(char spliter)
		{
			string s = Console.ReadLine();
			if (string.IsNullOrEmpty(s))
				return new int[] { };
			string[] ss = s.Split(spliter);
			int[] Res = new int[ss.Length];
			for (int i = 0; i < ss.Length; i++)
				Res[i] = int.Parse(ss[i]);
			return Res;
		}
		static int[] cins() { return cins(' '); }
		static void print(object j) { Console.WriteLine(j.ToString()); }
		static void print(string j) { Console.WriteLine(j); }
		#endregion
		static PriorityQueue<VT> Fish;

		static void Main(string[] args)
		{
			var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
			Console.SetOut(sw);
			Fish = new PriorityQueue<VT>(i => i.s);
			int[] I = cins();
			int q = I[1];
			HashSet<int> Unique = new HashSet<int>();
			for (int iop = 0; iop < q; iop++)
			{
				I = cins();
				if (!Unique.Contains(I[0]))
					Fish.Push(new VT(I[0], I[1]));
				else
				{
					int k = Fish.HeapIndex(I[0]);
					VT p = Fish.Access(k);
					Fish.Gain(new VT(I[0], p.V + I[1]), k);
				}
				var Res = Fish.Top;
				if (Res.V == 0) print("1 0");
				else print(string.Format("{0} {1}", Res.s, Res.V));
				Unique.Add(I[0]);
			}
			Console.Out.Flush();
		}
	}
}