Problem p03185 (C++)

Buggy submission (status: Runtime Error):
#include "bits/stdc++.h"
using namespace std;
#define mod 1000000007
#define dom 998244353
#define all(c) begin(c), end(c)
#define rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, a, b) for (int i = (b)-1; i >= (a); i--)
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
#define long long long
#define List vector
#define var auto
#define Count size()
#define Length size()
int dd[] = {0, 1, 0, -1, 0}; // →↓←↑

struct LiChaoTree {
  struct Line {
    long a, b;
    Line(long a, long b) {
      this->a = a;
      this->b = b;
    }
    long f(long x) { return a * x + b; }
  };
  int n;
  vector<Line> tr;
  Line ex = Line(0, LLONG_MAX);
  vector<long> X;

  // 動的CHT, M=(x座標の最大値)
  LiChaoTree(int M) {
    M++;
    n = 1;
    while (n < M)
      n <<= 1;
    tr.clear();
    tr.resize((n << 1) - 1, ex);
    X.clear();
    X.resize(n);
    for (int i = 0; i < n; i++)
      X[i] = i;
  }
  // クエリ先読み動的CHT Mが巨大なときに用いる
  // M=(x座標の最大値)
  // Q=(ソート済みであるx座標のクエリ配列)
  LiChaoTree(long M, vector<long> Q) {
    int n_ = Q.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    tr.clear();
    X.clear();
    X.resize(n);
    for (int i = 0; i < n_; i++)
      X[i] = Q[i];
    for (int i = n_; i < n; i++)
      X[i] = M << 1;
  }
  // 座標xにおけるy座標の最小値
  // j=(そのx座標のインデックス
  long query(int j) {
    long x = X[j];
    int i = j + n - 1;
    long ret = tr[i].f(x);
    while (i > 0) {
      i = i - 1 >> 1;
      ret = min(ret, tr[i].f(x));
    }
    return ret;
  }
  // 直線 y=ax+b を追加
  void add(long a, long b) { add(0, 0, n, Line(a, b)); }
  void add(int k, int l, int r, Line f) {
    long lx = X[l];
    long rx = X[r - 1];
    bool left = f.f(lx) < tr[k].f(lx);
    bool right = f.f(rx) < tr[k].f(rx);

    if (!left && !right)
      return;
    if (left && right) {
      tr[k] = f;
      return;
    }

    int m = l + r >> 1;
    long mx = X[m];
    bool mid = f.f(mx) < tr[k].f(mx);
    if (mid) {
      Line tmp = f;
      f = tr[k];
      tr[k] = tmp;
    }

    if (left != mid)
      add(k << 1 | 1, l, l + r >> 1, f);
    else
      add(k + 1 << 1, l + r >> 1, r, f);
  }
};
// 以下の漸化式は
// dp[i]=min_j (H[j]-H[i])^2 + dp[j] + C (j=[0,i-1])
// min_j (-2H[j] *H[i] +(H[j]^2+dp[j])) + (H[i]^2+C)
// と変形できるのでCHTで高速化できる。

void solve() {
  int N;
  cin >> N;
  long C;
  cin >> C;
  vector<long> dp(N);
  vector<long> H(N);
  rep(i, N) { cin >> H[i]; }
  LiChaoTree CHT((int)1e6, H);

  CHT.add(-2 * H[0], H[0] * H[0]);
  repi(j, 1, N) {
    dp[j] = H[j] * H[j] + C + CHT.query(j);
    CHT.add(-2 * H[j], dp[j] + H[j] * H[j]);
  }
  cout << dp[N - 1] << endl;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  solve();
  return 0;
}


Fixed submission:
#include "bits/stdc++.h"
using namespace std;
#define mod 1000000007
#define dom 998244353
#define all(c) begin(c), end(c)
#define rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, a, b) for (int i = (b)-1; i >= (a); i--)
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
#define long long long
#define List vector
#define var auto
#define Count size()
#define Length size()
int dd[] = {0, 1, 0, -1, 0}; // →↓←↑

struct LiChaoTree {
  struct Line {
    long a, b;
    Line(long a, long b) {
      this->a = a;
      this->b = b;
    }
    long f(long x) { return a * x + b; }
  };
  int n;
  vector<Line> tr;
  Line ex = Line(0, LLONG_MAX);
  vector<long> X;

  // 動的CHT, M=(x座標の最大値)
  LiChaoTree(int M) {
    M++;
    n = 1;
    while (n < M)
      n <<= 1;
    tr.clear();
    tr.resize((n << 1) - 1, ex);
    X.clear();
    X.resize(n);
    for (int i = 0; i < n; i++)
      X[i] = i;
  }
  // クエリ先読み動的CHT Mが巨大なときに用いる
  // M=(x座標の最大値)
  // Q=(ソート済みであるx座標のクエリ配列)
  LiChaoTree(long M, vector<long> Q) {
    int n_ = Q.size();
    n = 1;
    while (n < n_)
      n <<= 1;
    tr.clear();
    tr.resize((n << 1) - 1, ex);
    X.clear();
    X.resize(n);
    for (int i = 0; i < n_; i++)
      X[i] = Q[i];
    for (int i = n_; i < n; i++)
      X[i] = M << 1;
  }
  // 座標xにおけるy座標の最小値
  // j=(そのx座標のインデックス
  long query(int j) {
    long x = X[j];
    int i = j + n - 1;
    long ret = tr[i].f(x);
    while (i > 0) {
      i = i - 1 >> 1;
      ret = min(ret, tr[i].f(x));
    }
    return ret;
  }
  // 直線 y=ax+b を追加
  void add(long a, long b) { add(0, 0, n, Line(a, b)); }
  void add(int k, int l, int r, Line f) {
    long lx = X[l];
    long rx = X[r - 1];
    bool left = f.f(lx) < tr[k].f(lx);
    bool right = f.f(rx) < tr[k].f(rx);

    if (!left && !right)
      return;
    if (left && right) {
      tr[k] = f;
      return;
    }

    int m = l + r >> 1;
    long mx = X[m];
    bool mid = f.f(mx) < tr[k].f(mx);
    if (mid) {
      Line tmp = f;
      f = tr[k];
      tr[k] = tmp;
    }

    if (left != mid)
      add(k << 1 | 1, l, l + r >> 1, f);
    else
      add(k + 1 << 1, l + r >> 1, r, f);
  }
};
// 以下の漸化式は
// dp[i]=min_j (H[j]-H[i])^2 + dp[j] + C (j=[0,i-1])
// min_j (-2H[j] *H[i] +(H[j]^2+dp[j])) + (H[i]^2+C)
// と変形できるのでCHTで高速化できる。

void solve() {
  int N;
  cin >> N;
  long C;
  cin >> C;
  vector<long> dp(N);
  vector<long> H(N);
  rep(i, N) { cin >> H[i]; }
  LiChaoTree CHT((int)1e6, H);

  CHT.add(-2 * H[0], H[0] * H[0]);
  repi(j, 1, N) {
    dp[j] = H[j] * H[j] + C + CHT.query(j);
    CHT.add(-2 * H[j], dp[j] + H[j] * H[j]);
  }
  cout << dp[N - 1] << endl;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  solve();
  return 0;
}