// // Monge 単一始点最短路 // 頂点数 N+1 の DAG, 頂点 i, j 間のコスト f(i, j) が Monge であることを仮定 // O(N log N) // // verified // AtCoder EDPC Z - Frog 3 // https://atcoder.jp/contests/dp/tasks/dp_z // // Codeforces Round 189 (Div. 1) C. Kalila and Dimna in the Logging Industry // https://codeforces.com/contest/319/problem/C // // yukicoder No.705 ゴミ拾い Hard // https://yukicoder.me/problems/no/705 // // Reference: // noshi: 簡易版 LARSCH Algorithm // https://noshi91.hatenablog.com/entry/2023/02/18/005856 // #include using namespace std; //------------------------------// // Utility //------------------------------// using ll = long long; using i128 = __int128_t; using u128 = __uint128_t; using pint = pair; using pll = pair; using tll = array; using fll = array; using vint = vector; using vll = vector; using dint = deque; using dll = deque; using vvint = vector>; using vvll = vector>; using vpll = vector>; template using min_priority_queue = priority_queue, greater>; template inline bool chmax(S &a, T b) { return (a < b ? a = b, 1 : 0); } template inline bool chmin(S &a, T b) { return (a > b ? a = b, 1 : 0); } template inline auto maxll(S a, T b) { return max(ll(a), ll(b)); } template inline auto minll(S a, T b) { return min(ll(a), ll(b)); } template auto max(const T &a) { return *max_element(a.begin(), a.end()); } template auto min(const T &a) { return *min_element(a.begin(), a.end()); } template auto argmax(const T &a) { return max_element(a.begin(), a.end()) - a.begin(); } template auto argmin(const T &a) { return min_element(a.begin(), a.end()) - a.begin(); } template auto accum(const vector &a) { return accumulate(a.begin(), a.end(), T()); } template auto accum(const deque &a) { return accumulate(a.begin(), a.end(), T()); } #define REP(i, a) for (long long i = 0; i < (long long)(a); i++) #define REP2(i, a, b) for (long long i = a; i < (long long)(b); i++) #define RREP(i, a) for (long long i = (a)-1; i >= (long long)(0); --i) #define RREP2(i, a, b) for (long long i = (b)-1; i >= (long long)(a); --i) #define EB emplace_back #define PF push_front #define PB push_back #define MP make_pair #define FI first #define SE second #define ALL(x) x.begin(), x.end() #define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl // input template istream& operator >> (istream &is, vector &P) { for (int i = 0; i < (int)P.size(); ++i) cin >> P[i]; return is; } template istream& operator >> (istream &is, deque &P) { for (int i = 0; i < (int)P.size(); ++i) cin >> P[i]; return is; } template istream& operator >> (istream &is, vector> &P) { for (int i = 0; i < (int)P.size(); ++i) cin >> P[i]; return is; } // output template ostream& operator << (ostream &s, const pair &P) { return s << '<' << P.first << ", " << P.second << '>'; } template ostream& operator << (ostream &s, const array &P) { return s << '<' << P[0] << "," << P[1] << '>'; } template ostream& operator << (ostream &s, const array &P) { return s << '<' << P[0] << "," << P[1] << "," << P[2] << '>'; } template ostream& operator << (ostream &s, const array &P) { return s << '<' << P[0] << "," << P[1] << "," << P[2] << "," << P[3] << '>'; } template ostream& operator << (ostream &s, const vector &P) { for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; } template ostream& operator << (ostream &s, const deque &P) { for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; } template ostream& operator << (ostream &s, const vector> &P) { for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; } template ostream& operator << (ostream &s, const set &P) { for (auto it : P) { s << "<" << it << "> "; } return s; } template ostream& operator << (ostream &s, const multiset &P) { for (auto it : P) { s << "<" << it << "> "; } return s; } template ostream& operator << (ostream &s, const unordered_set &P) { for (auto it : P) { s << "<" << it << "> "; } return s; } template ostream& operator << (ostream &s, const map &P) { for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; } template ostream& operator << (ostream &s, const unordered_map &P) { for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; } void yes(bool a) { cout << (a ? "yes" : "no") << endl; } void YES(bool a) { cout << (a ? "YES" : "NO") << endl; } void Yes(bool a) { cout << (a ? "Yes" : "No") << endl; } const vector DX = {1, 0, -1, 0, 1, -1, 1, -1}; const vector DY = {0, 1, 0, -1, 1, -1, -1, 1}; // noshi's simplified LARSCH // find shortest path from vertex 0 on DAG with monotone cost in O(N log N) // vertex: 0, 1, 2, ..., N, f(i, j) must be Monge template struct MongeShortestPath { VAL INF = numeric_limits::max() / 2; int CNT_INF = numeric_limits::max() / 2; // results vector dp; vector cnt, prev; // solver template vector> solve(int N, const FUNC &f, bool minimize_cnt = true) { dp.assign(N + 1, INF); cnt.assign(N + 1, CNT_INF); prev.assign(N + 1, 0); dp[0] = 0, cnt[0] = 0; auto relax = [&](int l, int r) -> void { VAL val = dp[l] + f(l, r); int c = cnt[l] + 1; if (dp[r] > val || (dp[r] == val && (minimize_cnt ? c < cnt[r] : c > cnt[r]))) { dp[r] = val; cnt[r] = c; prev[r] = l; } }; auto rec = [&](auto &&rec, int l, int r) -> void { if (r - l <= 1) return; int m = (l + r) / 2; for (int k = prev[l]; k <= prev[r]; k++) relax(k, m); rec(rec, l, m); for (int k = l + 1; k <= m; k++) relax(k, r); rec(rec, m, r); }; if (N > 0) relax(0, N), rec(rec, 0, N); vector> res(N + 1, make_pair(numeric_limits::max() / 2, -1)); res[0].first = VAL(0); for (int i = 1; i <= N; i++) res[i] = {dp[i], prev[i]}; return res; } vector reconstruct() { int N = (int)dp.size() - 1; vector path; for (int v = N; v > 0; v = prev[v]) path.emplace_back(v); path.emplace_back(0); reverse(path.begin(), path.end()); return path; } }; //------------------------------// // Examples //------------------------------// // AtCoder EDPC Z - Frog 3 /* H は単調増加数列 chmin(dp[j], dp[i] + (H[j] - H[i])^2 + C) i -> j のコスト:(H[j] - H[i])^2 ...... 差の凸関数は Monge スタート: 0, ゴール: N-1 */ void EDPC_Z() { long long N, C; cin >> N >> C; vector H(N); for (long long i = 0; i < N; i++) cin >> H[i]; auto func = [&](int i, int j) -> long long { return (H[j] - H[i]) * (H[j] - H[i]) + C; }; MongeShortestPath msp; auto res = msp.solve(N-1, func); cout << res[N-1].first << endl; } // Codeforces Round 189 (Div. 1) C. Kalila and Dimna in the Logging Industry /* A: 単調増加, B: 単調減少, ともに長さ N i -> j のコストが、B[i] × A[j] で与えられる ..... 単調増加 × 単調減少は Monge スタート: 0, ゴール: N-1 */ void Codeforces_189_C() { long long N; cin >> N; vector A(N), B(N); for (int i = 0; i < N; i++) cin >> A[i]; for (int i = 0; i < N; i++) cin >> B[i]; auto func = [&](int i, int j) -> long long { return B[i] * A[j]; }; MongeShortestPath msp; auto res = msp.solve(N-1, func); cout << res[N-1].first << endl; } // yukicoder No.705 ゴミ拾い Hard /* A, X, Y: N 個 これらを区間に分割していく  dp[j] = min_{0 ≦ i < j}(dp[i] + |A[j-1] - X[i]|^3 + |-Y[i]|^3) i -> j のコスト:|A[j-1] - X[i]|^3 + |-Y[i]|^3 ...... 差の凸関数 (Monge) + 縞々 (Monge) -> Monge スタート: 0, ゴール: N */ void yukicoder_705() { int N; cin >> N; vector A(N), X(N), Y(N); for (int i = 0; i < N; i++) cin >> A[i]; for (int i = 0; i < N; i++) cin >> X[i]; for (int i = 0; i < N; i++) cin >> Y[i]; auto func = [&](int i, int j) -> long long { long long dx = abs(A[j-1] - X[i]), dy = abs(Y[i]); return dx * dx * dx + dy * dy * dy; }; MongeShortestPath msp; auto res = msp.solve(N, func); cout << res[N].first << endl; } int main() { //EDPC_Z(); //Codeforces_189_C(); yukicoder_705(); }