Problem p03182 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using P = pair<ll, ll>;
const ll INF = 5e15;
const ll MOD = 1e9 + 7;

/*
 * This LazySegmentTree is tree for query "ADD".
 * If you want to change query, you have to change the function "eval".
 * Too show where you have to change, I wrote the comment "!! TO CHANGE !!".
 */

class LazySegmentTree {
private:
  ll N, init;
  vector<ll> node, lazy;
  vector<bool> lazy_flag;

public:
  LazySegmentTree(const vector<ll> &v, ll init) {
    this->init = init;
    ll tmp = 1;
    while (tmp < v.size())
      tmp *= 2;
    N = tmp;
    node.resize(2 * N - 1);
    lazy.resize(2 * N - 1, init);
    lazy_flag.resize(2 * N - 1, init);
    for (ll i = 0; i < v.size(); i++) {
      node[i + N - 1] = v[i];
    }
    for (ll i = N - 2; 0 <= i; i--) {

      /*
       * !! TO CHANGE !!
       * You have to change the operator '+' between node[i * 2 + 1] and node[i
       * * 2 + 2]
       */
      node[i] = max(node[i * 2 + 1], node[i * 2 + 2]);
    }
  }

  /*
   * node[pos] -> [left, right)
   */
  void lazy_eval(ll pos, ll left, ll right) {
    if (!lazy_flag[pos]) {
      return;
    }

    /*
     * !! TO CHANGE !!
     * How to update the value node[pos] by using lazy[pos]
     */
    node[pos] += lazy[pos];
    lazy_flag[pos] = false;

    /*
     * whether the node is the bottom of tree or not.
     */
    if (right - left > 1) {

      /*
       * !! TO CHANGE !!
       * How to propagate the value to under node.
       * For example, when the query is "ADD", you have to add half of value to
       * under node.
       */
      lazy[2 * pos + 1] += lazy[pos];
      lazy[2 * pos + 2] += lazy[pos];
      lazy_flag[2 * pos + 1] = true;
      lazy_flag[2 * pos + 2] = true;
    }

    /*
     * !! TO CHANGE !!
     * Init lazy[pos] because it alredy has been evaluated.
     */
    lazy[pos] = init;
  }

  /*
   * If you want to call this func from out of class, in many cases you don't
   * have to change the args pos, node_left, node_right. Be careful that the
   * range is half-open interval. [left, right), [node_left, node_right)
   * @param left:         lower limit of interval of query
   * @param right:        upper limit of interval of query
   * @param val:          the value gave from query
   * @param node_left:    lower limit of interval of the node points.
   * @param node_right:   upper limit of interval of the node points.
   */
  void update_query(ll left, ll right, ll val, ll pos = 0, ll node_left = 0,
                    ll node_right = -1) {
    if (node_right < 0) {
      node_right = N;
    }

    /*
     * Execute lazy evaluation.
     */
    lazy_eval(pos, node_left, node_right);

    /*
     * If the node is out of inrerval, return.
     */
    if (right <= node_left || node_right <= left) {
      return;
    }

    /*
     * If the node cover the interval complety, update this->lazy and execute
     * lazy_eval. Else recursion.
     */
    if (left <= node_left && node_right <= right) {

      /*
       * !! TO CHANGE !!
       * How to propagate the val and how to summary the val..
       */
      lazy[pos] += val;
      lazy_flag[pos] = true;
      lazy_eval(pos, node_left, node_right);
    } else {

      /*
       * recursion
       */
      update_query(left, right, val, 2 * pos + 1, node_left,
                   (node_left + node_right) / 2);
      update_query(left, right, val, 2 * pos + 2, (node_left + node_right) / 2,
                   node_right);

      /*
       * !! TO CHANGE !!
       * How to summary the value under the node.
       */
      node[pos] = max(node[2 * pos + 1], node[2 * pos + 2]);
    }
  }

  ll get_query(ll left, ll right, ll pos = 0, ll node_left = 0,
               ll node_right = -1) {
    if (node_right < 0) {
      node_right = N;
    }

    /*
     * Evaluate the node[pos]
     */
    lazy_eval(pos, node_left, node_right);

    if (node_right <= left || right <= node_left) {
      return -INF;
    }
    if (left <= node_left && node_right <= right) {
      return node[pos];
    }

    /*
     * !! TO CHANGE !!
     * You have to change the mark '+' between get_query and get_query.
     */
    return max(get_query(left, right, 2 * pos + 1, node_left,
                         (node_left + node_right) / 2),
               get_query(left, right, 2 * pos + 2, (node_left + node_right) / 2,
                         node_right));
  }
};

int main() {
  ll N, M;
  cin >> N >> M;
  ll ans = 0;
  LazySegmentTree LST(vector<ll>(N + 10), 0);
  vector<ll> left(2 + 1e5 + 10, 0);
  map<ll, vector<P>> right;
  for (ll i = 0; i < M; i++) {
    ll l, r, a;
    cin >> l >> r >> a;
    left[l] += a;
    right[r].push_back(P(l, a));
  }
  for (ll i = 1; i <= N; i++) {
    LST.update_query(0, i, left[i]);
    ll val = LST.get_query(0, i);
    ans = max(ans, val);
    LST.update_query(i, i + 1, val);
    const auto &vec = right[i];
    for (const auto &p : vec) {
      LST.update_query(0, p.first, -p.second);
    }
  }
  cout << ans << endl;
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using P = pair<ll, ll>;
const ll INF = 5e15;
const ll MOD = 1e9 + 7;

/*
 * This LazySegmentTree is tree for query "ADD".
 * If you want to change query, you have to change the function "eval".
 * Too show where you have to change, I wrote the comment "!! TO CHANGE !!".
 */

class LazySegmentTree {
private:
  ll N, init;
  vector<ll> node, lazy;
  vector<bool> lazy_flag;

public:
  LazySegmentTree(const vector<ll> &v, ll init) {
    this->init = init;
    ll tmp = 1;
    while (tmp < v.size())
      tmp *= 2;
    N = tmp;
    node.resize(2 * N - 1);
    lazy.resize(2 * N - 1, init);
    lazy_flag.resize(2 * N - 1, init);
    for (ll i = 0; i < v.size(); i++) {
      node[i + N - 1] = v[i];
    }
    for (ll i = N - 2; 0 <= i; i--) {

      /*
       * !! TO CHANGE !!
       * You have to change the operator '+' between node[i * 2 + 1] and node[i
       * * 2 + 2]
       */
      node[i] = max(node[i * 2 + 1], node[i * 2 + 2]);
    }
  }

  /*
   * node[pos] -> [left, right)
   */
  void lazy_eval(ll pos, ll left, ll right) {
    if (!lazy_flag[pos]) {
      return;
    }

    /*
     * !! TO CHANGE !!
     * How to update the value node[pos] by using lazy[pos]
     */
    node[pos] += lazy[pos];
    lazy_flag[pos] = false;

    /*
     * whether the node is the bottom of tree or not.
     */
    if (right - left > 1) {

      /*
       * !! TO CHANGE !!
       * How to propagate the value to under node.
       * For example, when the query is "ADD", you have to add half of value to
       * under node.
       */
      lazy[2 * pos + 1] += lazy[pos];
      lazy[2 * pos + 2] += lazy[pos];
      lazy_flag[2 * pos + 1] = true;
      lazy_flag[2 * pos + 2] = true;
    }

    /*
     * !! TO CHANGE !!
     * Init lazy[pos] because it alredy has been evaluated.
     */
    lazy[pos] = init;
  }

  /*
   * If you want to call this func from out of class, in many cases you don't
   * have to change the args pos, node_left, node_right. Be careful that the
   * range is half-open interval. [left, right), [node_left, node_right)
   * @param left:         lower limit of interval of query
   * @param right:        upper limit of interval of query
   * @param val:          the value gave from query
   * @param node_left:    lower limit of interval of the node points.
   * @param node_right:   upper limit of interval of the node points.
   */
  void update_query(ll left, ll right, ll val, ll pos = 0, ll node_left = 0,
                    ll node_right = -1) {
    if (node_right < 0) {
      node_right = N;
    }

    /*
     * Execute lazy evaluation.
     */
    lazy_eval(pos, node_left, node_right);

    /*
     * If the node is out of inrerval, return.
     */
    if (right <= node_left || node_right <= left) {
      return;
    }

    /*
     * If the node cover the interval complety, update this->lazy and execute
     * lazy_eval. Else recursion.
     */
    if (left <= node_left && node_right <= right) {

      /*
       * !! TO CHANGE !!
       * How to propagate the val and how to summary the val..
       */
      lazy[pos] += val;
      lazy_flag[pos] = true;
      lazy_eval(pos, node_left, node_right);
    } else {

      /*
       * recursion
       */
      update_query(left, right, val, 2 * pos + 1, node_left,
                   (node_left + node_right) / 2);
      update_query(left, right, val, 2 * pos + 2, (node_left + node_right) / 2,
                   node_right);

      /*
       * !! TO CHANGE !!
       * How to summary the value under the node.
       */
      node[pos] = max(node[2 * pos + 1], node[2 * pos + 2]);
    }
  }

  ll get_query(ll left, ll right, ll pos = 0, ll node_left = 0,
               ll node_right = -1) {
    if (node_right < 0) {
      node_right = N;
    }

    /*
     * Evaluate the node[pos]
     */
    lazy_eval(pos, node_left, node_right);

    if (node_right <= left || right <= node_left) {
      return -INF;
    }
    if (left <= node_left && node_right <= right) {
      return node[pos];
    }

    /*
     * !! TO CHANGE !!
     * You have to change the mark '+' between get_query and get_query.
     */
    return max(get_query(left, right, 2 * pos + 1, node_left,
                         (node_left + node_right) / 2),
               get_query(left, right, 2 * pos + 2, (node_left + node_right) / 2,
                         node_right));
  }
};

int main() {
  ll N, M;
  cin >> N >> M;
  ll ans = 0;
  LazySegmentTree LST(vector<ll>(N + 10), 0);
  vector<ll> left(2 * 1e5 + 10, 0);
  map<ll, vector<P>> right;
  for (ll i = 0; i < M; i++) {
    ll l, r, a;
    cin >> l >> r >> a;
    left[l] += a;
    right[r].push_back(P(l, a));
  }
  for (ll i = 1; i <= N; i++) {
    LST.update_query(0, i, left[i]);
    ll val = LST.get_query(0, i);
    ans = max(ans, val);
    LST.update_query(i, i + 1, val);
    const auto &vec = right[i];
    for (const auto &p : vec) {
      LST.update_query(0, p.first, -p.second);
    }
  }
  cout << ans << endl;
  return 0;
}