论文:NOI2004年周源的论文《浅谈数形结合思想在信息学竞赛中的应用》,
参考:http://www.cnblogs.com/kuangbin/archive/2012/08/26/2657650.html
//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)
typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int MAXN = 500010;
int n, M;
int dp[MAXN];
int sum[MAXN];
int q[MAXN];
int be, ed;
int Up(int k, int j)
{
return dp[j] + sum[j] * sum[j] - (dp[k] + sum[k] * sum[k]);
}
int Down(int k, int j)
{
return (sum[j] - sum[k]) * 2;
}
int getDp(int i, int j)
{
return dp[j] + (sum[i] - sum[j]) * (sum[i] - sum[j]) + M;
}
int solve()
{
dp[0] = 0;
be = 1;
ed = 0;
q[++ed] = 0;///
for (int i = 1; i <= n; i++)
{
while (be < ed && Up(q[be], q[be + 1]) <= sum[i] * Down(q[be], q[be + 1]))
be++;
int j = q[be];
dp[i] = getDp(i, j);
while (be < ed && Up(q[ed - 1], q[ed]) * Down(q[ed], i) >= Up(q[ed], i) * Down(q[ed - 1], q[ed]))
ed--;
q[++ed] = i;
}
return dp[n];
}
int main ()
{
int x;
while (~RII(n, M))
{
sum[0] = 0;
FE(i, 1, n)
{
RI(x);
sum[i] = sum[i - 1] + x;
}
printf("%d\n", solve());
}
return 0;
}