#pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #include using namespace std; 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); } using pint = pair; using pll = pair; using tint = array; using tll = array; using fint = array; using fll = array; using vint = vector; using vll = vector; using ll = long long; using u32 = unsigned int; using u64 = unsigned long long; using int128 = __int128; using u128 = unsigned __int128; template using min_priority_queue = priority_queue, greater>; #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 PB push_back #define MP make_pair #define MT make_tuple #define FI first #define SE second #define ALL(x) x.begin(), x.end() #define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl // debug stream template ostream& operator << (ostream &s, pair P) { return s << '<' << P.first << ", " << P.second << '>'; } template ostream& operator << (ostream &s, vector P) { for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; } template ostream& operator << (ostream &s, deque P) { for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; } template ostream& operator << (ostream &s, vector > P) { for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; } template ostream& operator << (ostream &s, set P) { for (auto it : P) { s << "<" << it << "> "; } return s; } template ostream& operator << (ostream &s, multiset P) { for (auto it : P) { s << "<" << it << "> "; } return s; } template ostream& operator << (ostream &s, map P) { for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; } // Convex Hull Trick /* 追加クエリの直線の傾きが単調減少の場合 - insert (a, b): add y = ax + b - query (x): min_i{a[i]*x + b} */ template struct CHT { using Line = pair; deque lines; inline bool check(const Line &a, const Line &b, const Line &c) { return (b.first - a.first) * (c.second - b.second) >= (b.second - a.second) * (c.first - b.first); } inline T get(int k, T x) { assert(k >= 0 && k < lines.size()); return lines[k].first * x + lines[k].second; } void insert(T a, T b) { Line l(a, b); while (lines.size() >= 2 && check(lines[(int)lines.size()-2], lines[(int)lines.size()-1], l)) { lines.pop_back(); } lines.push_back(l); } T query(T x) { int low = -1, high = (int)lines.size(); while (high - low > 1) { int mid = (low + high) / 2; if (get(mid, x) >= get(mid + 1, x)) low = mid; else high = mid; } return get(high, x); } // クエリの単調性も成り立つ場合 (x が単調増加) T query_monotone(T x) { while (lines.size() >= 2 && get(0, x) >= get(1, x)) lines.pop_front(); if (lines.empty()) return 1LL<<60; return lines[0].first * x + lines[0].second; } }; int main() { int N; cin >> N; vector A(N), S(N+1, 0); REP(i, N) { cin >> A[i]; S[i+1] = S[i] + A[i]; } ll MAX = 1LL<<29, INF = 1LL<<60; vector> chts(N+1, CHT()); vector dp(N+1, vector(N+1, vector(2, INF))); // 0: 白で終わる, 1: 黒で終わる vector mdp(N+2, vector(N+1, INF)); auto push = [&](int i, int j) -> void { // auto func = [i, j, &S, &dp](ll x) -> ll { // return dp[i][j][0] + S[i-j]*S[i-j] // }; chts[i-j].insert(-S[i]*2, S[i]*S[i] + dp[i][j][0]); chmin(mdp[i+1][j], min(mdp[i][j], dp[i][j][1])); }; dp[0][0][0] = 0, dp[0][0][1] = 0; push(0, 0); REP2(i, 1, N+1) { //COUT(i); REP(j, i+1) { // 0 -> 1 // REP2(k, 0, j) { // chmin(dp[i][j][1], dp[i-j+k][k][0] + (S[i] - S[i-j+k]) * (S[i] - S[i-j+k])); // } // (dp[i-j][0][0] + S[i]² - 2S[i]S[i-j] + S[i-j]² // dp[i-j+1][1][0] + S[i]² - 2S[i]S[i-j+1] + S[i-j+1]² // ... // dp[i-1][j-1][0] + S[i]² - 2S[i]S[i-1] + S[i-1]² chmin(dp[i][j][1], chts[i-j].query_monotone(S[i]) + S[i] * S[i]); // 1 -> 0 // REP(k, i) { // chmin(dp[i][j][0], dp[k][j][1]); // } chmin(dp[i][j][0], mdp[i][j]); //cout << i << ", " << j << ": " << make_pair(dp[i][j][0], dp[i][j][1]) << endl; push(i, j); } } REP2(k, 1, N+1) { cout << min(dp[N][k][0], dp[N][k][1]) << endl; } }