Problem p02758 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cfloat>
#include <complex>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/time.h>
#include <unordered_map>
#include <vector>

#define fs first
#define sc second

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

const ll mod = 998244353;

#define MAX_N 210000
int dat[2 * MAX_N - 1];

template <typename T> class SegTree {
public:
  // セグメント木を持つグローバル変数
  int n;

  void init(int n_, T init_num) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++) {
      dat[i] = init_num;
    }
  }

  // k番目の値(0-indexed)をaに変更
  void update(int k, T a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  // [a, b)の最小値を求める。
  // kは節点の番号、l, rはその節点が[l, r)に対応づいていることを表す。
  // query(a, b, 0, 0, n)で外からは呼び出す。
private:
  T query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) {
      return 0;
    }

    if (a <= l && r <= b) {
      return dat[k];
    } else {
      ll vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      ll vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return max(vl, vr);
    }
  }
  // [a, b)の最小値を求める。
public:
  T query(int a, int b) { return query(a, b, 0, 0, this->n); }
};

inline ll take_mod(ll a) { return (a % mod + mod) % mod; }

inline ll add(ll a, ll b) { return take_mod(a + b); }

inline ll sub(ll a, ll b) { return take_mod(a - b); }

inline ll mul(ll a, ll b) { return take_mod(a * b); }

inline ll pow(ll x, ll n) {
  ll res = 1LL;
  while (n > 0) {
    if (n & 1)
      res = mul(res, x);
    x = mul(x, x);
    n >>= 1;
  }
  return res;
}

ll mod_inv(ll x) { return pow(x, mod - 2); }

vector<ll> dp(210000, 0);
vector<int> next1(210000, -1);
vector<int> next2(210000, -1);

int main() {
  int n;
  cin >> n;
  vector<P> x2;
  for (int i = 0; i < n; i++) {
    ll xx, dd;
    cin >> xx >> dd;
    x2.emplace_back(P(xx, dd));
  }
  sort(x2.begin(), x2.end());

  vector<ll> x(n, 0), d(n, 0);
  for (int i = 0; i < n; i++) {
    x[i] = x2[i].fs;
    d[i] = x2[i].sc;
  }

  SegTree<int> st;
  st.init(n, -1);
  for (int i = 0; i < n; i++) {
    st.update(i, i + 1);
  }

  for (int i = n - 1; i >= 0; i--) {
    int next_ind = lower_bound(x.begin(), x.end(), x[i] + d[i]) - x.begin();
    if (i + 1 == next_ind) {
      next1[i] = i + 1;
    } else {
      next1[i] = st.query(i + 1, next_ind);
    }
    st.update(i, next1[i]);
  }

  dp[0] = 1;

  for (int i = 0; i < n; i++) {
    // 選ぶ場合
    int nex = st.query(i, i + 1);
    dp[nex] = add(dp[nex], dp[i]);
    // 選ばない場合
    dp[i + 1] = add(dp[i + 1], dp[i]);
  }
  cout << dp[n] << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cfloat>
#include <complex>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/time.h>
#include <unordered_map>
#include <vector>

#define fs first
#define sc second

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

const ll mod = 998244353;

#define MAX_N 410000
int dat[2 * MAX_N - 1];

template <typename T> class SegTree {
public:
  // セグメント木を持つグローバル変数
  int n;

  void init(int n_, T init_num) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++) {
      dat[i] = init_num;
    }
  }

  // k番目の値(0-indexed)をaに変更
  void update(int k, T a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  // [a, b)の最小値を求める。
  // kは節点の番号、l, rはその節点が[l, r)に対応づいていることを表す。
  // query(a, b, 0, 0, n)で外からは呼び出す。
private:
  T query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) {
      return 0;
    }

    if (a <= l && r <= b) {
      return dat[k];
    } else {
      ll vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      ll vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return max(vl, vr);
    }
  }
  // [a, b)の最小値を求める。
public:
  T query(int a, int b) { return query(a, b, 0, 0, this->n); }
};

inline ll take_mod(ll a) { return (a % mod + mod) % mod; }

inline ll add(ll a, ll b) { return take_mod(a + b); }

inline ll sub(ll a, ll b) { return take_mod(a - b); }

inline ll mul(ll a, ll b) { return take_mod(a * b); }

inline ll pow(ll x, ll n) {
  ll res = 1LL;
  while (n > 0) {
    if (n & 1)
      res = mul(res, x);
    x = mul(x, x);
    n >>= 1;
  }
  return res;
}

ll mod_inv(ll x) { return pow(x, mod - 2); }

vector<ll> dp(210000, 0);
vector<int> next1(210000, -1);
vector<int> next2(210000, -1);

int main() {
  int n;
  cin >> n;
  vector<P> x2;
  for (int i = 0; i < n; i++) {
    ll xx, dd;
    cin >> xx >> dd;
    x2.emplace_back(P(xx, dd));
  }
  sort(x2.begin(), x2.end());

  vector<ll> x(n, 0), d(n, 0);
  for (int i = 0; i < n; i++) {
    x[i] = x2[i].fs;
    d[i] = x2[i].sc;
  }

  SegTree<int> st;
  st.init(n, -1);
  for (int i = 0; i < n; i++) {
    st.update(i, i + 1);
  }

  for (int i = n - 1; i >= 0; i--) {
    int next_ind = lower_bound(x.begin(), x.end(), x[i] + d[i]) - x.begin();
    if (i + 1 == next_ind) {
      next1[i] = i + 1;
    } else {
      next1[i] = st.query(i + 1, next_ind);
    }
    st.update(i, next1[i]);
  }

  dp[0] = 1;

  for (int i = 0; i < n; i++) {
    // 選ぶ場合
    int nex = st.query(i, i + 1);
    dp[nex] = add(dp[nex], dp[i]);
    // 選ばない場合
    dp[i + 1] = add(dp[i + 1], dp[i]);
  }
  cout << dp[n] << endl;

  return 0;
}