Problem p03736 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rep2(i, x, n) for (int i = x; i <= n; i++)
#define rep3(i, x, n) for (int i = x; i >= n; i--)
#define elif else if
#define sp setprecision
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<int, ll> pil;
typedef pair<ll, int> pli;
typedef pair<ld, ld> pdd;
const ll MOD = 1e9 + 7;
// const ll MOD = 998244353;
const int inf = 1e8;
const ll INF = 1e16;
const string alpha = "abcdefghijklmnopqrstuvwxyz";

using T = ll;
const int MAX_V = 2e5;
// 演算の内容
T f(T a, T b) { return min(a, b); }
// 何で初期化するか
T other = 1e18;

struct segment_tree {
  int n;
  T seg[2 * MAX_V];
  // 要素数N(0〜N-1)の初期化されたセグメント木を構築
  segment_tree(int N) {
    n = 1;
    while (n < N)
      n *= 2;
    fill_n(seg, 2 * n - 1, other);
  }
  // i番目の要素をxに変更(0番目から数える)
  void update(int i, T x) {
    i += n - 1;
    seg[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      seg[i] = f(seg[2 * i + 1], seg[2 * i + 2]);
    }
  }
  // query(a, b)で[a, b)における演算の結果を取得
  T query(int a, int b, int i = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (a >= r || b <= l)
      return other;
    elif (a <= l && r <= b) return seg[i];
    else {
      T vl = query(a, b, 2 * i + 1, l, (l + r) / 2);
      T vr = query(a, b, 2 * i + 2, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
};

int main() {
  int N, Q, A;
  cin >> N >> Q >> A;
  A--;
  int x[Q + 1];
  rep(i, Q + 1) {
    cin >> x[i];
    x[i]--;
  }
  segment_tree seg1(N), seg2(N);
  rep(i, N) {
    seg1.update(i, INF + i);
    seg2.update(i, INF - i);
  }
  seg1.update(A, A);
  seg2.update(A, -A);
  ll sum = 0;
  rep(i, Q) {
    ll tmp = INF;
    tmp = min(tmp, seg1.query(x[i + 1], N) - x[i + 1]);
    tmp = min(tmp, seg2.query(0, x[i + 1]) + x[i + 1]);
    ll c = tmp - seg1.query(x[i], x[i] + 1) + x[i];
    ll d = abs(x[i + 1] - x[i]);
    if (c < d) {
      seg1.update(x[i], seg1.query(x[i], x[i] + 1) + c - d);
      seg2.update(x[i], seg2.query(x[i], x[i] + 1) + c - d);
    }
    sum += d;
  }
  ll ans = INF;
  rep(i, N) { ans = min(ans, sum + seg1.query(i, i + 1) - i); }
  cout << ans << endl;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rep2(i, x, n) for (int i = x; i <= n; i++)
#define rep3(i, x, n) for (int i = x; i >= n; i--)
#define elif else if
#define sp setprecision
#define pb(x) push_back(x)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<int, ll> pil;
typedef pair<ll, int> pli;
typedef pair<ld, ld> pdd;
const ll MOD = 1e9 + 7;
// const ll MOD = 998244353;
const int inf = 1e8;
const ll INF = 1e16;
const string alpha = "abcdefghijklmnopqrstuvwxyz";

using T = ll;
const int MAX_V = 5e5;
// 演算の内容
T f(T a, T b) { return min(a, b); }
// 何で初期化するか
T other = 1e18;

struct segment_tree {
  int n;
  T seg[2 * MAX_V];
  // 要素数N(0〜N-1)の初期化されたセグメント木を構築
  segment_tree(int N) {
    n = 1;
    while (n < N)
      n *= 2;
    fill_n(seg, 2 * n - 1, other);
  }
  // i番目の要素をxに変更(0番目から数える)
  void update(int i, T x) {
    i += n - 1;
    seg[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      seg[i] = f(seg[2 * i + 1], seg[2 * i + 2]);
    }
  }
  // query(a, b)で[a, b)における演算の結果を取得
  T query(int a, int b, int i = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (a >= r || b <= l)
      return other;
    elif (a <= l && r <= b) return seg[i];
    else {
      T vl = query(a, b, 2 * i + 1, l, (l + r) / 2);
      T vr = query(a, b, 2 * i + 2, (l + r) / 2, r);
      return f(vl, vr);
    }
  }
};

int main() {
  int N, Q, A;
  cin >> N >> Q >> A;
  A--;
  int x[Q + 1];
  rep(i, Q + 1) {
    cin >> x[i];
    x[i]--;
  }
  segment_tree seg1(N), seg2(N);
  rep(i, N) {
    seg1.update(i, INF + i);
    seg2.update(i, INF - i);
  }
  seg1.update(A, A);
  seg2.update(A, -A);
  ll sum = 0;
  rep(i, Q) {
    ll tmp = INF;
    tmp = min(tmp, seg1.query(x[i + 1], N) - x[i + 1]);
    tmp = min(tmp, seg2.query(0, x[i + 1]) + x[i + 1]);
    ll c = tmp - seg1.query(x[i], x[i] + 1) + x[i];
    ll d = abs(x[i + 1] - x[i]);
    if (c < d) {
      seg1.update(x[i], seg1.query(x[i], x[i] + 1) + c - d);
      seg2.update(x[i], seg2.query(x[i], x[i] + 1) + c - d);
    }
    sum += d;
  }
  ll ans = INF;
  rep(i, N) { ans = min(ans, sum + seg1.query(i, i + 1) - i); }
  cout << ans << endl;
}