Problem p02758 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)

typedef long long ll;
typedef pair<ll, ll> P;
const ll INF = 1LL << 60;

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

ll modpow(ll a, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  // 元配列 v をセグメント木で表現する
  SegmentTree(vector<int> v) {
    // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
    // セグメント木全体で必要なノード数は 2n-1 個である
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1, -1);

    // 最下段に値を入れたあとに、下の段から順番に値を入れる
    // 値を入れるには、自分の子の 2 値を参照すれば良い
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  void update(int x, int val) {
    // 最下段のノードにアクセスする
    x += (n - 1);

    // 最下段のノードを更新したら、あとは親に上って更新していく
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない -> 適当に返す
    if (r <= a || b <= l)
      return -1;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (a <= l && r <= b)
      return node[k];

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }
};

ll dp[2][100100];

const ll MOD = 998244353;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  cin >> N;

  vector<pair<ll, ll>> R(N);

  ll x, d;
  rep(i, N) {
    cin >> x >> d;
    R[i] = make_pair(x, d);
  }

  R.push_back(make_pair(3 * 1e9, 1LL));

  sort(R.begin(), R.end());

  vector<int> BOOT(N + 1);
  rep(i, N + 1) BOOT[i] = -1;
  SegmentTree st(BOOT);

  for (int i = N - 1; i >= 0; i--) {

    int ind = upper_bound(R.begin(), R.end(),
                          make_pair(R[i].first + R[i].second, 0LL)) -
              R.begin();
    st.update(i, i);
    int max_val = st.getmax(i, ind);
    st.update(i, max_val);
    BOOT[i] = max_val;
  }

  dp[0][N] = 1;
  dp[1][N] = 0;

  for (int i = N - 1; i >= 0; i--) {

    // ここのind取得を工夫する
    // int ind = upper_bound(R.begin(), R.end(), make_pair(R[i].first +
    // R[i].second, 0LL)) - R.begin();

    dp[0][i] = (dp[0][i + 1] + dp[1][i + 1]) % MOD;

    dp[1][i] = (dp[0][BOOT[i] + 1] + dp[1][BOOT[i] + 1]) % MOD;
  }

  cout << (dp[0][0] + dp[1][0]) % MOD << endl;

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)

typedef long long ll;
typedef pair<ll, ll> P;
const ll INF = 1LL << 60;

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

ll modpow(ll a, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  // 元配列 v をセグメント木で表現する
  SegmentTree(vector<int> v) {
    // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
    // セグメント木全体で必要なノード数は 2n-1 個である
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1, -1);

    // 最下段に値を入れたあとに、下の段から順番に値を入れる
    // 値を入れるには、自分の子の 2 値を参照すれば良い
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  void update(int x, int val) {
    // 最下段のノードにアクセスする
    x += (n - 1);

    // 最下段のノードを更新したら、あとは親に上って更新していく
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない -> 適当に返す
    if (r <= a || b <= l)
      return -1;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (a <= l && r <= b)
      return node[k];

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }
};

ll dp[2][200100];

const ll MOD = 998244353;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  cin >> N;

  vector<pair<ll, ll>> R(N);

  ll x, d;
  rep(i, N) {
    cin >> x >> d;
    R[i] = make_pair(x, d);
  }

  R.push_back(make_pair(3 * 1e9, 1LL));

  sort(R.begin(), R.end());

  vector<int> BOOT(N + 1);
  rep(i, N + 1) BOOT[i] = -1;
  SegmentTree st(BOOT);

  for (int i = N - 1; i >= 0; i--) {

    int ind = upper_bound(R.begin(), R.end(),
                          make_pair(R[i].first + R[i].second, 0LL)) -
              R.begin();
    st.update(i, i);
    int max_val = st.getmax(i, ind);
    st.update(i, max_val);
    BOOT[i] = max_val;
  }

  dp[0][N] = 1;
  dp[1][N] = 0;

  for (int i = N - 1; i >= 0; i--) {

    // ここのind取得を工夫する
    // int ind = upper_bound(R.begin(), R.end(), make_pair(R[i].first +
    // R[i].second, 0LL)) - R.begin();

    dp[0][i] = (dp[0][i + 1] + dp[1][i + 1]) % MOD;

    dp[1][i] = (dp[0][BOOT[i] + 1] + dp[1][BOOT[i] + 1]) % MOD;
  }

  cout << (dp[0][0] + dp[1][0]) % MOD << endl;

  return 0;
}