Problem p02549 (C++)

Buggy submission (status: Runtime Error):
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

// template
#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define ALL(v) (v).begin(), (v).end()
typedef long long int ll;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;
const double eps = 1e-12;
template <typename T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
// end

template <unsigned mod = 998244353> struct fp {
  int v;
  static unsigned get_mod() { return mod; }
  int inv() const {
    int tmp, a = v, b = mod, x = 1, y = 0;
    while (b)
      tmp = a / b, a -= tmp * b, swap(a, b), x -= tmp * y, swap(x, y);
    if (x < 0) {
      x += mod;
    }
    return x;
  }
  fp() : v(0) {}
  fp(ll x) : v(x >= 0 ? x % mod : mod + (x % mod)) {}
  fp operator-() const { return fp(-v); }
  fp pow(ll t) {
    fp res = 1, b = *this;
    while (t) {
      if (t & 1)
        res *= b;
      b *= b;
      t >>= 1;
    }
    return res;
  }
  fp &operator+=(const fp &x) {
    if ((v += x.v) >= (int)mod)
      v -= mod;
    return *this;
  }
  fp &operator-=(const fp &x) {
    if ((v += mod - x.v) >= (int)mod)
      v -= mod;
    return *this;
  }
  fp &operator*=(const fp &x) {
    v = ll(v) * x.v % mod;
    return *this;
  }
  fp &operator/=(const fp &x) {
    v = ll(v) * x.inv() % mod;
    return *this;
  }
  fp operator+(const fp &x) const { return fp(*this) += x; }
  fp operator-(const fp &x) const { return fp(*this) -= x; }
  fp operator*(const fp &x) const { return fp(*this) *= x; }
  fp operator/(const fp &x) const { return fp(*this) /= x; }
  bool operator==(const fp &x) const { return v == x.v; }
  bool operator!=(const fp &x) const { return v != x.v; }
};
using Fp = fp<>;

template <typename M, typename N = M> struct LazySegmentTree {
  using F = function<M(M, M)>;
  using G = function<M(M, N)>;
  using H = function<N(N, N)>;
  int sz, height;
  vector<M> data;
  vector<N> lazy;
  const F f;
  const G g;
  const H h;
  const M m1;
  const N n1;
  LazySegmentTree(int n, const F f, const G g, const H h, const M &m1,
                  const N n1)
      : f(f), g(g), h(h), m1(m1), n1(n1) {
    sz = 1, height = 0;
    while (sz < n)
      sz <<= 1, height++;
    data.assign(2 * sz, m1);
    lazy.assign(2 * sz, n1);
  }
  void build(vector<M> v) {
    rep(i, 0, v.size()) data[i + sz] = v[i];
    for (int k = sz - 1; k > 0; k--)
      data[k] = f(data[2 * k], data[2 * k + 1]);
  }
  M ref(int k) { return lazy[k] == n1 ? data[k] : g(data[k], lazy[k]); }
  void recalc(int k) {
    while (k >>= 1)
      data[k] = f(ref(2 * k), ref(2 * k + 1));
  }
  void thrust(int k) {
    for (int i = height; i > 0; i--)
      eval(k >> i);
  }
  void eval(int k) {
    if (lazy[k] != n1) {
      lazy[2 * k] = h(lazy[2 * k], lazy[k]);
      lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
      data[k] = ref(k);
      lazy[k] = n1;
    }
  }
  void set(int a, M x) {
    thrust(a += sz);
    data[a] = x;
    recalc(a);
  }
  void update(int a, int b, N x) {
    thrust(a += sz);
    thrust(b += sz - 1);
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        lazy[l] = h(lazy[l], x), ++l;
      if (r & 1)
        --r, lazy[r] = h(lazy[r], x);
    }
    recalc(a);
    recalc(b);
  }
  M query(int a, int b) {
    thrust(a += sz);
    thrust(b += sz - 1);
    M L = m1, R = m1;
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        L = f(L, ref(l++));
      if (r & 1)
        R = f(ref(--r), R);
    }
    return f(L, R);
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> lb(k), rb(k);
  rep(i, 0, k) {
    cin >> lb[i] >> rb[i];
    rb[i]++;
  }
  auto f = [&](Fp a, Fp b) { return a + b; };
  auto g = [&](Fp a, Fp b) { return a + b; };
  auto h = [&](Fp a, Fp b) { return a + b; };
  LazySegmentTree<Fp, Fp> seg(n + 10, f, g, h, 0, 0);
  seg.update(0, 1, 1);
  rep(i, 0, n) {
    Fp x = seg.query(i, i + 1);
    rep(j, 0, k) { seg.update(i + lb[j], i + rb[j], x); }
  }
  Fp res = seg.query(n - 1, n);
  cout << res.v << endl;
  return 0;
}

Fixed submission:
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

// template
#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define ALL(v) (v).begin(), (v).end()
typedef long long int ll;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;
const double eps = 1e-12;
template <typename T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
// end

template <unsigned mod = 998244353> struct fp {
  int v;
  static unsigned get_mod() { return mod; }
  int inv() const {
    int tmp, a = v, b = mod, x = 1, y = 0;
    while (b)
      tmp = a / b, a -= tmp * b, swap(a, b), x -= tmp * y, swap(x, y);
    if (x < 0) {
      x += mod;
    }
    return x;
  }
  fp() : v(0) {}
  fp(ll x) : v(x >= 0 ? x % mod : mod + (x % mod)) {}
  fp operator-() const { return fp(-v); }
  fp pow(ll t) {
    fp res = 1, b = *this;
    while (t) {
      if (t & 1)
        res *= b;
      b *= b;
      t >>= 1;
    }
    return res;
  }
  fp &operator+=(const fp &x) {
    if ((v += x.v) >= (int)mod)
      v -= mod;
    return *this;
  }
  fp &operator-=(const fp &x) {
    if ((v += mod - x.v) >= (int)mod)
      v -= mod;
    return *this;
  }
  fp &operator*=(const fp &x) {
    v = ll(v) * x.v % mod;
    return *this;
  }
  fp &operator/=(const fp &x) {
    v = ll(v) * x.inv() % mod;
    return *this;
  }
  fp operator+(const fp &x) const { return fp(*this) += x; }
  fp operator-(const fp &x) const { return fp(*this) -= x; }
  fp operator*(const fp &x) const { return fp(*this) *= x; }
  fp operator/(const fp &x) const { return fp(*this) /= x; }
  bool operator==(const fp &x) const { return v == x.v; }
  bool operator!=(const fp &x) const { return v != x.v; }
};
using Fp = fp<>;

template <typename M, typename N = M> struct LazySegmentTree {
  using F = function<M(M, M)>;
  using G = function<M(M, N)>;
  using H = function<N(N, N)>;
  int sz, height;
  vector<M> data;
  vector<N> lazy;
  const F f;
  const G g;
  const H h;
  const M m1;
  const N n1;
  LazySegmentTree(int n, const F f, const G g, const H h, const M &m1,
                  const N n1)
      : f(f), g(g), h(h), m1(m1), n1(n1) {
    sz = 1, height = 0;
    while (sz < n)
      sz <<= 1, height++;
    data.assign(2 * sz, m1);
    lazy.assign(2 * sz, n1);
  }
  void build(vector<M> v) {
    rep(i, 0, v.size()) data[i + sz] = v[i];
    for (int k = sz - 1; k > 0; k--)
      data[k] = f(data[2 * k], data[2 * k + 1]);
  }
  M ref(int k) { return lazy[k] == n1 ? data[k] : g(data[k], lazy[k]); }
  void recalc(int k) {
    while (k >>= 1)
      data[k] = f(ref(2 * k), ref(2 * k + 1));
  }
  void thrust(int k) {
    for (int i = height; i > 0; i--)
      eval(k >> i);
  }
  void eval(int k) {
    if (lazy[k] != n1) {
      lazy[2 * k] = h(lazy[2 * k], lazy[k]);
      lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
      data[k] = ref(k);
      lazy[k] = n1;
    }
  }
  void set(int a, M x) {
    thrust(a += sz);
    data[a] = x;
    recalc(a);
  }
  void update(int a, int b, N x) {
    thrust(a += sz);
    thrust(b += sz - 1);
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        lazy[l] = h(lazy[l], x), ++l;
      if (r & 1)
        --r, lazy[r] = h(lazy[r], x);
    }
    recalc(a);
    recalc(b);
  }
  M query(int a, int b) {
    thrust(a += sz);
    thrust(b += sz - 1);
    M L = m1, R = m1;
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        L = f(L, ref(l++));
      if (r & 1)
        R = f(ref(--r), R);
    }
    return f(L, R);
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> lb(k), rb(k);
  rep(i, 0, k) {
    cin >> lb[i] >> rb[i];
    rb[i]++;
  }
  auto f = [&](Fp a, Fp b) { return a + b; };
  auto g = [&](Fp a, Fp b) { return a + b; };
  auto h = [&](Fp a, Fp b) { return a + b; };
  LazySegmentTree<Fp, Fp> seg(n + 10, f, g, h, 0, 0);
  seg.update(0, 1, 1);
  rep(i, 0, n) {
    Fp x = seg.query(i, i + 1);
    rep(j, 0, k) {
      int L = min(i + lb[j], n), R = min(i + rb[j], n);
      seg.update(L, R, x);
    }
  }
  Fp res = seg.query(n - 1, n);
  cout << res.v << endl;
  return 0;
}