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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
	private	static			BufferedReader	br      = null;
	private	static	final	int				MAP_ID  = 0;
	private	static	final	int				MAP_NUM = 1;
	private	static	final	int				MAP_MAX = 2;

	static {
		br = new BufferedReader(new InputStreamReader(System.in));
	}
 
    /**
     * @param args
     */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[]	head = parseData();

		if (head != null) {
			if (head[0] > 0) {
				int		tl  = 1;
				int[][]	map = null;

				while (tl < head[0]) {
					tl*=2;
				}

				map = new int[MAP_MAX][tl*2+1];
				Arrays.fill(map[MAP_NUM], Integer.MIN_VALUE);

				for(int l = 0; l < head[0]; l++) {
					map[MAP_ID][tl+l]  = l+1;
					map[MAP_NUM][tl+l] = 0;
				}

				for (int q = 0; q < head[1]; q++) {
					int[]	node = parseData();

					map[MAP_NUM][tl+node[0]-1] += node[1];
					updateTree((tl+node[0]-1)>>1, map);
					System.out.println(map[MAP_ID][1] + " " + map[MAP_NUM][1]);
				}
			}
		}
	}

	private static void updateTree(int i, int[][] map) {
		for (; i > 0; i = i>>1) {
			int	L = 2*i;
			int	R = 2*i+1;
			if(map[MAP_NUM][L]==map[MAP_NUM][R]){
				map[MAP_NUM][i] = map[MAP_NUM][L];
				map[MAP_ID][i]  = Math.min(map[MAP_ID][L], map[MAP_ID][R]);
			}
			else if(map[MAP_NUM][L] < map[MAP_NUM][R]){
				map[MAP_NUM][i] = map[MAP_NUM][R];
				map[MAP_ID][i]  = map[MAP_ID][R];
			}
			else{
				map[MAP_NUM][i] = map[MAP_NUM][L];
				map[MAP_ID][i]  = map[MAP_ID][L];
			}
		}
	}

	private static int[] parseData() {
		int[]	data = null;
		String	str  = null;

		if ((str = parseStdin()) != null) {
			String[]	lines = str.split(" ");

			if (lines.length > 0) {
				data = new int[lines.length];
				data[0] = Integer.parseInt(lines[0]);
				data[1] = Integer.parseInt(lines[1]);
			}
		}

		return data;
	}

	private static String parseStdin() {
        String  stdin = null;
        
        try {
        	String  tmp = br.readLine();
        	if (tmp != null) {
            	if (!tmp.isEmpty()) {
            		stdin = tmp;
            	}
        	}
        }
        catch (IOException e) {}
 
        return stdin;
	}
}