Problem p02549 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define ff first
#define ss second
#define ll long long
#define ld long double
#define pb push_back
#define eb emplace_back
#define pii pair<int, int>
#define vi vector<int>
#define vl vector<ll>
#define vii vector<pii>
#define sws                                                                    \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL);                                                               \
  cout.tie(NULL);
#define endl '\n'
#define teto(a, b) (((a) + (b)-1) / (b))
#define all(x) x.begin(), x.end()
#define forn(i, n) for (int i = 0; i < (int)n; i++)
#define forne(i, a, b) for (int i = a; i <= b; i++)
#define dbg(msg, var) cerr << msg << " " << var << endl;

using namespace std;

const int MAX = 100010;
const ll MOD = 998244353;
const int INF = 0x3f3f3f3f;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
const ld EPS = 1e-7;

const int LOG = ceil(log2(MAX));

// End Template //

namespace seg {
ll seg[2 * MAX], lazy[2 * MAX];
int n;

ll junta(ll a, ll b) { return (a + b) % MOD; }

// soma x na posicao p de tamanho tam
void poe(int p, ll x, int tam, bool prop = 1) {
  seg[p] += x * tam;
  seg[p] %= MOD;
  if (prop and p < n)
    lazy[p] += x;
}

// atualiza todos os pais da folha p
void sobe(int p) {
  for (int tam = 2; p /= 2; tam *= 2) {
    seg[p] = junta(seg[2 * p], seg[2 * p + 1]);
    poe(p, lazy[p], tam, 0);
  }
}

// propaga o caminho da raiz ate a folha p
void prop(int p) {
  int tam = 1 << (LOG - 1);
  for (int s = LOG; s; s--, tam /= 2) {
    int i = p >> s;
    if (lazy[i]) {
      poe(2 * i, lazy[i], tam);
      poe(2 * i + 1, lazy[i], tam);
      lazy[i] = 0;
    }
  }
}

void build(int n2) {
  n = n2;
  for (int i = n - 1; i; i--)
    seg[i] = junta(seg[2 * i], seg[2 * i + 1]);
  for (int i = 0; i < 2 * n; i++)
    lazy[i] = 0;
}

ll query(int a, int b) {
  ll ret = 0;
  for (prop(a += n), prop(b += n); a <= b; ++a /= 2, --b /= 2) {
    if (a % 2 == 1)
      ret = junta(ret, seg[a]);
    if (b % 2 == 0)
      ret = junta(ret, seg[b]);
  }
  return ret;
}

void update(int a, int b, int x) {
  int a2 = a += n, b2 = b += n, tam = 1;
  for (; a <= b; ++a /= 2, --b /= 2, tam *= 2) {
    if (a % 2 == 1)
      poe(a, x, tam);
    if (b % 2 == 0)
      poe(b, x, tam);
  }
  sobe(a2), sobe(b2);
}
}; // namespace seg

int main() {
  sws;

  int n, k, l, r;
  cin >> n >> k;
  vii S;

  seg::build(n + 10);
  seg::update(1, 1, 1);
  for (int i = 0; i < k; i++) {
    cin >> l >> r;
    S.pb({l, r});
  }

  for (int i = 1; i <= n; i++) {
    ll val = seg::query(i, i);
    // cout << "i, val = " << i << " " << val << endl;
    for (auto s : S)
      seg::update(min(i + s.ff, n + 1), min(i + s.ss, n + 1), val);
  }

  cout << seg::query(n, n) << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
#define ff first
#define ss second
#define ll long long
#define ld long double
#define pb push_back
#define eb emplace_back
#define pii pair<int, int>
#define vi vector<int>
#define vl vector<ll>
#define vii vector<pii>
#define sws                                                                    \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL);                                                               \
  cout.tie(NULL);
#define endl '\n'
#define teto(a, b) (((a) + (b)-1) / (b))
#define all(x) x.begin(), x.end()
#define forn(i, n) for (int i = 0; i < (int)n; i++)
#define forne(i, a, b) for (int i = a; i <= b; i++)
#define dbg(msg, var) cerr << msg << " " << var << endl;

using namespace std;

const int MAX = 200010;
const ll MOD = 998244353;
const int INF = 0x3f3f3f3f;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
const ld EPS = 1e-7;

const int LOG = ceil(log2(MAX));

// End Template //

namespace seg {
ll seg[2 * MAX], lazy[2 * MAX];
int n;

ll junta(ll a, ll b) { return (a + b) % MOD; }

// soma x na posicao p de tamanho tam
void poe(int p, ll x, int tam, bool prop = 1) {
  seg[p] += x * tam;
  seg[p] %= MOD;
  if (prop and p < n)
    lazy[p] += x;
}

// atualiza todos os pais da folha p
void sobe(int p) {
  for (int tam = 2; p /= 2; tam *= 2) {
    seg[p] = junta(seg[2 * p], seg[2 * p + 1]);
    poe(p, lazy[p], tam, 0);
  }
}

// propaga o caminho da raiz ate a folha p
void prop(int p) {
  int tam = 1 << (LOG - 1);
  for (int s = LOG; s; s--, tam /= 2) {
    int i = p >> s;
    if (lazy[i]) {
      poe(2 * i, lazy[i], tam);
      poe(2 * i + 1, lazy[i], tam);
      lazy[i] = 0;
    }
  }
}

void build(int n2) {
  n = n2;
  for (int i = n - 1; i; i--)
    seg[i] = junta(seg[2 * i], seg[2 * i + 1]);
  for (int i = 0; i < 2 * n; i++)
    lazy[i] = 0;
}

ll query(int a, int b) {
  ll ret = 0;
  for (prop(a += n), prop(b += n); a <= b; ++a /= 2, --b /= 2) {
    if (a % 2 == 1)
      ret = junta(ret, seg[a]);
    if (b % 2 == 0)
      ret = junta(ret, seg[b]);
  }
  return ret;
}

void update(int a, int b, int x) {
  int a2 = a += n, b2 = b += n, tam = 1;
  for (; a <= b; ++a /= 2, --b /= 2, tam *= 2) {
    if (a % 2 == 1)
      poe(a, x, tam);
    if (b % 2 == 0)
      poe(b, x, tam);
  }
  sobe(a2), sobe(b2);
}
}; // namespace seg

int main() {
  sws;

  int n, k, l, r;
  cin >> n >> k;
  vii S;

  seg::build(n + 10);
  seg::update(1, 1, 1);
  for (int i = 0; i < k; i++) {
    cin >> l >> r;
    S.pb({l, r});
  }

  for (int i = 1; i <= n; i++) {
    ll val = seg::query(i, i);
    // cout << "i, val = " << i << " " << val << endl;
    for (auto s : S)
      seg::update(min(i + s.ff, n + 1), min(i + s.ss, n + 1), val);
  }

  cout << seg::query(n, n) << endl;

  return 0;
}