Problem p00099 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (int i = 0; i < (n); i++)
#define repi(i, a, b) for (int i = (a); i < (b); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
// segment-tree
ll n; // nは2のべき乗
pii dat[1000110 * 2 - 1];

// 初期化
void init(ll _n) {
  // べき乗を計算しておく
  n = 1;
  while (n < _n)
    n *= 2;
  // すべての値をINT_MAXに
  for (ll i = 0; i < 2 * n - 1; i++) {
    dat[i].first = -INF;
  }
}

// i番目の値(0-indexed)をxに変更
void update(ll i, ll x, ll c) {
  // 葉のノード番号
  i += n - 1;
  dat[i].first = x;
  dat[i].second = -c;
  while (i > 0) {
    i = (i - 1) / 2;
    if (dat[i * 2 + 1] > dat[i * 2 + 2]) {
      dat[i] = dat[i * 2 + 1];
    } else {
      dat[i] = dat[i * 2 + 2];
    }
  }
}

//[a,b)の最小値,l,rにはノードkに対応づく区画を与える
// 外からはquery(a,b,0,0,n)のように呼ぶ
/*int query(int a,int b,int k,int l,int r){
  if(r <=a||b <=l)//交差しない
        return INT_MAX;
  if(a <=l&&r<=b)//完全に含む
        return dat[k].first;
  else{
        int vl =query(a, b, k*2+1, l, (l+r)/2);
        int vr =query(a, b, k*2+2, (l+r)/2, r);
        return min(vl,vr);
  }
}*/
int main() {
  int q;
  cin >> n >> q;
  init(n);
  for (int i = 0; i < q; i++) {
    ll x, y;
    cin >> x >> y;
    x--;
    ll tmp = x + n - 1;
    if (dat[tmp].first != -INF) {
      update(x, dat[tmp].first + y, x);
    } else {
      update(x, y, x);
    }
    cout << -1 * dat[0].second + 1 << " " << dat[0].first << endl;
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (int i = 0; i < (n); i++)
#define repi(i, a, b) for (int i = (a); i < (b); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
// segment-tree
ll n; // nは2のべき乗
pii dat[2000110 * 2 - 1];

// 初期化
void init(ll _n) {
  // べき乗を計算しておく
  n = 1;
  while (n < _n)
    n *= 2;
  // すべての値をINT_MAXに
  for (ll i = 0; i < 2 * n - 1; i++) {
    dat[i].first = -INF;
  }
}

// i番目の値(0-indexed)をxに変更
void update(ll i, ll x, ll c) {
  // 葉のノード番号
  i += n - 1;
  dat[i].first = x;
  dat[i].second = -c;
  while (i > 0) {
    i = (i - 1) / 2;
    if (dat[i * 2 + 1] > dat[i * 2 + 2]) {
      dat[i] = dat[i * 2 + 1];
    } else {
      dat[i] = dat[i * 2 + 2];
    }
  }
}

//[a,b)の最小値,l,rにはノードkに対応づく区画を与える
// 外からはquery(a,b,0,0,n)のように呼ぶ
/*int query(int a,int b,int k,int l,int r){
  if(r <=a||b <=l)//交差しない
        return INT_MAX;
  if(a <=l&&r<=b)//完全に含む
        return dat[k].first;
  else{
        int vl =query(a, b, k*2+1, l, (l+r)/2);
        int vr =query(a, b, k*2+2, (l+r)/2, r);
        return min(vl,vr);
  }
}*/
int main() {
  int q;
  cin >> n >> q;
  init(n);
  for (int i = 0; i < q; i++) {
    ll x, y;
    cin >> x >> y;
    x--;
    ll tmp = x + n - 1;
    if (dat[tmp].first != -INF) {
      update(x, dat[tmp].first + y, x);
    } else {
      update(x, y, x);
    }
    cout << -1 * dat[0].second + 1 << " " << dat[0].first << endl;
  }
  return 0;
}