Problem p02758 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rep2(i, x, n) for (int i = x; i <= n; i++)
#define rep3(i, x, n) for (int i = x; i >= n; i--)
#define elif else if
#define sp setprecision
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<int, ll> pil;
typedef pair<ll, int> pli;
typedef pair<ld, ld> pdd;
// const ll MOD = 1e9+7;
const ll MOD = 998244353;
const int inf = 1e8;
const ll INF = 1e16;
const string alpha = "abcdefghijklmnopqrstuvwxyz";

using T = ll;
const int MAX_V = 2e5;
// 演算の内容
T f(T a, T b) { return max(a, b); }
// 何で初期化するか
T other = 0;

struct segment_tree {
  int n;
  T seg[2 * MAX_V];
  // 要素数N(0〜N-1)の初期化されたセグメント木を構築
  segment_tree(int N) {
    n = 1;
    while (n < N)
      n *= 2;
    fill_n(seg, 2 * n - 1, other);
  }
  // i番目の要素をxに変更(0番目から数える)
  void update(int i, T x) {
    i += n - 1;
    seg[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      seg[i] = f(seg[2 * i + 1], seg[2 * i + 2]);
    }
  }
  // query(a, b)で[a, b)における演算の結果を取得
  T query(int a, int b, int i = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (a >= r || b <= l)
      return other;
    elif (a <= l && r <= b) return seg[i];
    else {
      T vl = query(a, b, 2 * i + 1, l, (l + r) / 2);
      T vr = query(a, b, 2 * i + 2, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
};

int main() {
  int N;
  cin >> N;
  pll p[N];
  rep(i, N) {
    ll x, d;
    cin >> x >> d;
    p[i] = pll(x, x + d);
  }
  sort(p, p + N);
  ll L[N], R[N];
  rep(i, N) { L[i] = p[i].first, R[i] = p[i].second; }
  segment_tree seg(N);
  rep(i, N) { seg.update(i, i); }
  rep3(i, N - 1, 0) {
    int j = lower_bound(L, L + N, R[i]) - L;
    seg.update(i, seg.query(i, j));
  }
  // a[i]:=i個目のロボットを起動したときにどこまで消滅するか
  int a[N];
  rep(i, N) {
    a[i] = seg.query(i, i + 1);
    // cout << a[i] << endl;
  }
  // dp[i]:=起動させるロボットがi番目以降のものだけであるときの組み合わせの数
  ll dp[N + 1];
  dp[N] = 1;
  rep3(i, N - 1, 0) {
    dp[i] = dp[i + 1] + dp[a[i] + 1];
    dp[i] %= MOD;
  }
  cout << dp[0] << endl;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rep2(i, x, n) for (int i = x; i <= n; i++)
#define rep3(i, x, n) for (int i = x; i >= n; i--)
#define elif else if
#define sp setprecision
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<int, ll> pil;
typedef pair<ll, int> pli;
typedef pair<ld, ld> pdd;
// const ll MOD = 1e9+7;
const ll MOD = 998244353;
const int inf = 1e8;
const ll INF = 1e16;
const string alpha = "abcdefghijklmnopqrstuvwxyz";

using T = ll;
const int MAX_V = 5e5;
// 演算の内容
T f(T a, T b) { return max(a, b); }
// 何で初期化するか
T other = 0;

struct segment_tree {
  int n;
  T seg[2 * MAX_V];
  // 要素数N(0〜N-1)の初期化されたセグメント木を構築
  segment_tree(int N) {
    n = 1;
    while (n < N)
      n *= 2;
    fill_n(seg, 2 * n - 1, other);
  }
  // i番目の要素をxに変更(0番目から数える)
  void update(int i, T x) {
    i += n - 1;
    seg[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      seg[i] = f(seg[2 * i + 1], seg[2 * i + 2]);
    }
  }
  // query(a, b)で[a, b)における演算の結果を取得
  T query(int a, int b, int i = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (a >= r || b <= l)
      return other;
    elif (a <= l && r <= b) return seg[i];
    else {
      T vl = query(a, b, 2 * i + 1, l, (l + r) / 2);
      T vr = query(a, b, 2 * i + 2, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
};

int main() {
  int N;
  cin >> N;
  pll p[N];
  rep(i, N) {
    ll x, d;
    cin >> x >> d;
    p[i] = pll(x, x + d);
  }
  sort(p, p + N);
  ll L[N], R[N];
  rep(i, N) { L[i] = p[i].first, R[i] = p[i].second; }
  segment_tree seg(N);
  rep(i, N) { seg.update(i, i); }
  rep3(i, N - 1, 0) {
    int j = lower_bound(L, L + N, R[i]) - L;
    seg.update(i, seg.query(i, j));
  }
  // a[i]:=i個目のロボットを起動したときにどこまで消滅するか
  int a[N];
  rep(i, N) {
    a[i] = seg.query(i, i + 1);
    // cout << a[i] << endl;
  }
  // dp[i]:=起動させるロボットがi番目以降のものだけであるときの組み合わせの数
  ll dp[N + 1];
  dp[N] = 1;
  rep3(i, N - 1, 0) {
    dp[i] = dp[i + 1] + dp[a[i] + 1];
    dp[i] %= MOD;
  }
  cout << dp[0] << endl;
}