Problem p03295 (C++)

Buggy submission (status: Runtime Error):
//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using ull = unsigned long long;

template <typename T> vector<T> make_vec_nd(T init, size_t size) {
  return vector<T>(size, init);
}
template <typename T, typename... Args>
auto make_vec_nd(T init, size_t size, Args... rest) {
  auto inner = make_vec_nd(init, rest...);
  return vector<decltype(inner)>(size, inner);
}

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

template <typename Monoid> struct SegmentTree {
  using Op = function<Monoid(const Monoid &lhs, const Monoid &rhs)>;
  size_t width;
  vector<Monoid> node;
  Op op;
  Monoid unit;

  SegmentTree(const vector<Monoid> &elems, Op op, Monoid unit)
      : op(op), unit(unit) {
    width = 1;
    while (width < elems.size()) {
      width *= 2;
    }
    node.resize(2 * width - 1, unit);
    for (size_t i = 0; i < elems.size(); i++) {
      node[i + width - 1] = elems[i];
    }
    for (size_t i = width - 2; i != numeric_limits<size_t>::max(); i--) {
      node[i] = op(node[2 * i + 1], node[2 * i + 2]);
    }
  }
  void update(size_t idx, Monoid elem) {
    idx += width - 1;
    node[idx] = elem;
    while (idx >= 1) {
      idx = (idx - 1) / 2;
      node[idx] = op(node[2 * idx + 1], node[2 * idx + 2]);
    }
  }
  Monoid query(size_t a, size_t b, size_t root = 0) const {
    assert(0 <= a && b <= width);
    size_t left = root, right = root;
    while (left < width - 1) {
      left = 2 * left + 1;
    }
    left -= (width - 1);
    while (right < width - 1) {
      right = 2 * right + 2;
    }
    right -= (width - 1);
    right++;
    if (right <= a || b <= left) {
      return unit;
    }
    if (a <= left && right <= b) {
      return node[root];
    }
    Monoid ans_l = query(a, b, 2 * root + 1);
    Monoid ans_r = query(a, b, 2 * root + 2);
    return op(ans_l, ans_r);
  }
};

int main() {
  ll N, M;
  cin >> N >> M;
  using Range = pair<ll, ll>;
  unordered_map<ll, Range> right_to_range;
  rep(i, 0, M) {
    ll a, b;
    cin >> a >> b;
    a--;
    b--;
    if (right_to_range.find(b) != right_to_range.end()) {
      Range elem = right_to_range[b];
      if (b - a < elem.second - elem.first) {
        right_to_range[b] = {a, b};
      }
    } else {
      right_to_range[b] = {a, b};
    }
  }
  vector<Range> ranges_pre;
  rep(i, 0, N) {
    if (right_to_range.find(i) != right_to_range.end()) {
      ranges_pre.push_back(right_to_range[i]);
    }
  }
  vector<Range> ranges;
  ranges.push_back(ranges_pre[0]);
  rep(i, 1, N) {
    if (ranges_pre[i].first > ranges.back().first) {
      ranges.push_back(ranges_pre[i]);
    }
  }
  right_to_range.clear();
  rep(i, 0, ranges.size()) { right_to_range[ranges[i].second] = ranges[i]; }
  vector<ll> elems(N - 1, numeric_limits<ll>::max());
  SegmentTree<ll> dp(
      elems, [](ll lhs, ll rhs) { return min(lhs, rhs); },
      numeric_limits<ll>::max());
  if (right_to_range.find(1) != right_to_range.end()) {
    dp.update(0, 1);
  } else {
    dp.update(0, 0);
  }
  rep(i, 1, N - 1) {
    if (right_to_range.find(i + 1) != right_to_range.end()) {
      Range added = right_to_range[i + 1];
      ll len = added.second - added.first;
      ll mn = dp.query(max((ll)0, i - len), i);
      dp.update(i, mn + 1);
    } else {
      dp.update(i, dp.query(i - 1, i));
    }
  }
  cout << dp.query(N - 2, N - 1) << endl;
}


Fixed submission:
//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using ull = unsigned long long;

template <typename T> vector<T> make_vec_nd(T init, size_t size) {
  return vector<T>(size, init);
}
template <typename T, typename... Args>
auto make_vec_nd(T init, size_t size, Args... rest) {
  auto inner = make_vec_nd(init, rest...);
  return vector<decltype(inner)>(size, inner);
}

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

template <typename Monoid> struct SegmentTree {
  using Op = function<Monoid(const Monoid &lhs, const Monoid &rhs)>;
  size_t width;
  vector<Monoid> node;
  Op op;
  Monoid unit;

  SegmentTree(const vector<Monoid> &elems, Op op, Monoid unit)
      : op(op), unit(unit) {
    width = 1;
    while (width < elems.size()) {
      width *= 2;
    }
    node.resize(2 * width - 1, unit);
    for (size_t i = 0; i < elems.size(); i++) {
      node[i + width - 1] = elems[i];
    }
    for (size_t i = width - 2; i != numeric_limits<size_t>::max(); i--) {
      node[i] = op(node[2 * i + 1], node[2 * i + 2]);
    }
  }
  void update(size_t idx, Monoid elem) {
    idx += width - 1;
    node[idx] = elem;
    while (idx >= 1) {
      idx = (idx - 1) / 2;
      node[idx] = op(node[2 * idx + 1], node[2 * idx + 2]);
    }
  }
  Monoid query(size_t a, size_t b, size_t root = 0) const {
    assert(0 <= a && b <= width);
    size_t left = root, right = root;
    while (left < width - 1) {
      left = 2 * left + 1;
    }
    left -= (width - 1);
    while (right < width - 1) {
      right = 2 * right + 2;
    }
    right -= (width - 1);
    right++;
    if (right <= a || b <= left) {
      return unit;
    }
    if (a <= left && right <= b) {
      return node[root];
    }
    Monoid ans_l = query(a, b, 2 * root + 1);
    Monoid ans_r = query(a, b, 2 * root + 2);
    return op(ans_l, ans_r);
  }
};

int main() {
  ll N, M;
  cin >> N >> M;
  using Range = pair<ll, ll>;
  unordered_map<ll, Range> right_to_range;
  rep(i, 0, M) {
    ll a, b;
    cin >> a >> b;
    a--;
    b--;
    if (right_to_range.find(b) != right_to_range.end()) {
      Range elem = right_to_range[b];
      if (b - a < elem.second - elem.first) {
        right_to_range[b] = {a, b};
      }
    } else {
      right_to_range[b] = {a, b};
    }
  }
  vector<Range> ranges_pre;
  rep(i, 0, N) {
    if (right_to_range.find(i) != right_to_range.end()) {
      ranges_pre.push_back(right_to_range[i]);
    }
  }
  vector<Range> ranges;
  ranges.push_back(ranges_pre[0]);
  rep(i, 1, ranges_pre.size()) {
    if (ranges_pre[i].first > ranges.back().first) {
      ranges.push_back(ranges_pre[i]);
    }
  }
  right_to_range.clear();
  rep(i, 0, ranges.size()) { right_to_range[ranges[i].second] = ranges[i]; }
  vector<ll> elems(N - 1, numeric_limits<ll>::max());
  SegmentTree<ll> dp(
      elems, [](ll lhs, ll rhs) { return min(lhs, rhs); },
      numeric_limits<ll>::max());
  if (right_to_range.find(1) != right_to_range.end()) {
    dp.update(0, 1);
  } else {
    dp.update(0, 0);
  }
  rep(i, 1, N - 1) {
    if (right_to_range.find(i + 1) != right_to_range.end()) {
      Range added = right_to_range[i + 1];
      ll len = added.second - added.first;
      ll mn = dp.query(max((ll)0, i - len), i);
      dp.update(i, mn + 1);
    } else {
      dp.update(i, dp.query(i - 1, i));
    }
  }
  cout << dp.query(N - 2, N - 1) << endl;
}