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: Time Limit Exceeded)

#include <stdio.h>

#define DEBUG 0

typedef struct _MEMBER MEMBER;

typedef struct _MEMBER {
    int no;
    int fish;
    MEMBER *prev;
    MEMBER *next;
} MEMBER;

MEMBER data[1000001];

int main(void)
{
    int N, Q;
    int i;
    int A, V;
    MEMBER *head;
    MEMBER *tail;
    MEMBER *p;
	
    
    scanf("%d%d", &N, &Q);

    if (N == 1){    // 参加者がひとりのときの処理
        data[1].fish = 0;
        for (i = 0; i < Q; i++){
            scanf("%d%d", &A, &V);
            data[1].fish += V;
            
            printf("%d %d", 1, data[1].fish);
        }
        
        return (0);
    }
    
    // リストの初期化
    
    data[1].no = 1;
    data[1].fish = 0;
    data[1].prev = NULL;
    data[1].next = &data[2];
    
    
    for (i = 2; i <= N - 1; i++){
        data[i].no = i;
        data[i].fish = 0;
        data[i].prev = &data[i - 1];
        data[i].next = &data[i + 1];
    }

    data[N].no = N;
    data[N].fish = 0;
    data[N].prev = &data[N - 1];
    data[N].next = NULL;

    head = &data[1];
    tail = &data[N];

#if DEBUG
p = head;
while (p != NULL){
    printf("[%d=%d]", p->no, p->fish);
    p = p->next;
}
printf("\n");
p = tail;
while (p != NULL){
    printf("(%d=%d)", p->no, p->fish);
    p = p->prev;
}
printf("\n");

#endif    
    
    for (i = 0; i < Q; i++){
        scanf("%d%d", &A, &V);
        data[A].fish += V;
        if (data[A].fish < 0){
            data[A].fish = 0;
        }
        
        
        // リストからはずす
        if (data[A].prev == NULL){  //先頭
            data[A].next->prev = NULL;
            head = data[A].next;
        }
        else if (data[A].next == NULL){  //末尾
            data[A].prev->next = NULL;
            tail = data[A].prev;
        }
        else {
            data[A].prev->next = data[A].next;
            data[A].next->prev = data[A].prev;
        }
        
        // リストに追加
        if (head->fish < data[A].fish || 
            (head->fish == data[A].fish && head->no > A)){ // 先頭
            
            data[A].prev = NULL;
            data[A].next = head;
            head->prev = &data[A];
            head = &data[A];
//printf("<先頭>\n");        
        } else if (tail->fish > data[A].fish || 
                       (tail->fish == data[A].fish && tail->no < A)){ // 末尾
            
            data[A].prev = tail;
            data[A].next = NULL;
            tail->next = &data[A];
            tail = &data[A];
//printf("<末尾>\n");        
       
        }
        else {
			// 挿入位置を検索
			p = head;
			while (p->fish > data[A].fish ||
			       (p->fish == data[A].fish && p->no < A)){
				   	
				p = p->next;
			}
			

            // 挿入位置に挿入
            data[A].next = p;
            data[A].prev = p->prev;
            p->prev->next = &data[A];
            p->prev = &data[A];
//printf("<中間>\n");        

        }

#if DEBUG
p = head;
while (p != NULL){
    printf("[%d=%d]", p->no, p->fish);
    p = p->next;
}
printf("\n");
p = tail;
while (p != NULL){
    printf("(%d=%d)", p->no, p->fish);
    p = p->prev;
}
printf("\n");
#endif    


        
        // 最大の表示
        printf("%d %d\n", head->no, head->fish);
    }
    
    return (0);
}