Problem p02549 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define M 998244353
long long tree[400005], dp[200001], lazy[400005];
void build(int node, int start, int end) {
  if (start == end) {
    // Leaf node will have a single element
    tree[node] = dp[start];
  } else {
    int mid = (start + end) / 2;
    // Recurse on the left child
    build(2 * node, start, mid);
    // Recurse on the right child
    build(2 * node + 1, mid + 1, end);
    // Internal node will have the sum of both of its children
    tree[node] = (tree[2 * node] + tree[2 * node + 1]) % M;
  }
}
void updateRange(int node, int start, int end, int l, int r, int val) {
  if (lazy[node] != 0) {
    // This node needs to be updated
    tree[node] += (end - start + 1) * lazy[node]; // Update it
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2] %= M; // Mark child as lazy
      lazy[node * 2 + 1] += lazy[node];
      lazy[node * 2 + 1] %= M; // Mark child as lazy
    }
    lazy[node] = 0; // Reset it
  }
  if (start > end or start > r or
      end < l) // Current segment is not within range [l, r]
    return;
  if (start >= l and end <= r) {
    // Segment is fully within range
    tree[node] += ((end - start + 1) * val) % M;
    tree[node] %= M;
    if (start != end) {
      // Not leaf node
      lazy[node * 2] += val;
      lazy[node * 2] %= M;
      lazy[node * 2 + 1] += val;
      lazy[node * 2 + 1] %= M;
    }
    return;
  }
  int mid = (start + end) / 2;
  updateRange(node * 2, start, mid, l, r, val);       // Updating left child
  updateRange(node * 2 + 1, mid + 1, end, l, r, val); // Updating right child
  tree[node] =
      (tree[node * 2] + tree[node * 2 + 1]) % M; // Updating root with max value
}

int queryRange(int node, int start, int end, int l, int r) {
  if (start > end or start > r or end < l)
    return 0; // Out of range
  if (lazy[node] != 0) {
    // This node needs to be updated
    tree[node] += ((end - start + 1) * lazy[node]) % M;
    tree[node] %= M; // Update it
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2] %= M; // Mark child as lazy
      lazy[node * 2 + 1] += lazy[node];
      lazy[node * 2 + 1] %= M; // Mark child as lazy
    }
    lazy[node] = 0; // Reset it
  }
  if (start >= l and end <= r) // Current segment is totally within range [l, r]
    return tree[node];
  int mid = (start + end) / 2;
  int p1 = queryRange(node * 2, start, mid, l, r);       // Query left child
  int p2 = queryRange(node * 2 + 1, mid + 1, end, l, r); // Query right child
  return (p1 + p2) % M;
}
int main() {
// your code goes here
#ifndef ONLINE_JUDGE
  freopen("input.txt", "r", stdin);
  freopen("res.txt", "w", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int n, k;
  cin >> n >> k;
  int l[k], r[k], li = 0;
  for (int i = 0; i < k; i++)
    cin >> l[i] >> r[i];
  for (int i = 0; i <= n; i++)
    dp[i] = 0;
  dp[1] = 1;
  build(1, 1, n);
  // cout<<tree[5]<<endl;
  for (int i = 1; i <= n; i++) {
    dp[i] = queryRange(1, 1, n, i, i) % M;
    // cout<<dp[i]<<endl;
    for (int j = 0; j < k; j++) {
      if (i + l[j] <= n)
        updateRange(1, 1, n, i + l[j], min(i + r[j], n), dp[i] % M);
    }
  }
  // for(int i=1;i<n;i++)
  //	dp[i]+=dp[i-1];
  cout << dp[n] % M;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define M 998244353
long long tree[5000050], dp[3000005], lazy[5000050];
void build(int node, int start, int end) {
  if (start == end) {
    // Leaf node will have a single element
    tree[node] = dp[start];
  } else {
    int mid = (start + end) / 2;
    // Recurse on the left child
    build(2 * node, start, mid);
    // Recurse on the right child
    build(2 * node + 1, mid + 1, end);
    // Internal node will have the sum of both of its children
    tree[node] = (tree[2 * node] + tree[2 * node + 1]) % M;
  }
}
void updateRange(int node, int start, int end, int l, int r, int val) {
  if (lazy[node] != 0) {
    // This node needs to be updated
    tree[node] += (end - start + 1) * lazy[node]; // Update it
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2] %= M; // Mark child as lazy
      lazy[node * 2 + 1] += lazy[node];
      lazy[node * 2 + 1] %= M; // Mark child as lazy
    }
    lazy[node] = 0; // Reset it
  }
  if (start > end or start > r or
      end < l) // Current segment is not within range [l, r]
    return;
  if (start >= l and end <= r) {
    // Segment is fully within range
    tree[node] += ((end - start + 1) * val) % M;
    tree[node] %= M;
    if (start != end) {
      // Not leaf node
      lazy[node * 2] += val;
      lazy[node * 2] %= M;
      lazy[node * 2 + 1] += val;
      lazy[node * 2 + 1] %= M;
    }
    return;
  }
  int mid = (start + end) / 2;
  updateRange(node * 2, start, mid, l, r, val);       // Updating left child
  updateRange(node * 2 + 1, mid + 1, end, l, r, val); // Updating right child
  tree[node] =
      (tree[node * 2] + tree[node * 2 + 1]) % M; // Updating root with max value
}

int queryRange(int node, int start, int end, int l, int r) {
  if (start > end or start > r or end < l)
    return 0; // Out of range
  if (lazy[node] != 0) {
    // This node needs to be updated
    tree[node] += ((end - start + 1) * lazy[node]) % M;
    tree[node] %= M; // Update it
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2] %= M; // Mark child as lazy
      lazy[node * 2 + 1] += lazy[node];
      lazy[node * 2 + 1] %= M; // Mark child as lazy
    }
    lazy[node] = 0; // Reset it
  }
  if (start >= l and end <= r) // Current segment is totally within range [l, r]
    return tree[node];
  int mid = (start + end) / 2;
  int p1 = queryRange(node * 2, start, mid, l, r);       // Query left child
  int p2 = queryRange(node * 2 + 1, mid + 1, end, l, r); // Query right child
  return (p1 + p2) % M;
}
int main() {
// your code goes here
#ifndef ONLINE_JUDGE
  freopen("input.txt", "r", stdin);
  freopen("res.txt", "w", stdout);
#endif
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int n, k;
  cin >> n >> k;
  int l[k], r[k], li = 0;
  for (int i = 0; i < k; i++)
    cin >> l[i] >> r[i];
  for (int i = 0; i <= n; i++)
    dp[i] = 0;
  dp[1] = 1;
  build(1, 1, n);
  // cout<<tree[5]<<endl;
  for (int i = 1; i <= n; i++) {
    dp[i] = queryRange(1, 1, n, i, i) % M;
    // cout<<dp[i]<<endl;
    for (int j = 0; j < k; j++) {
      if (i + l[j] <= n)
        updateRange(1, 1, n, i + l[j], min(i + r[j], n), dp[i] % M);
    }
  }
  // for(int i=1;i<n;i++)
  //	dp[i]+=dp[i-1];
  cout << dp[n] % M;
  return 0;
}