#include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma warning(disable:4996) typedef long long ll; #define MIN(a, b) ((a)>(b)? (b): (a)) #define MAX(a, b) ((a)<(b)? (b): (a)) #define LINF 9223300000000000000 #define INF 2140000000 const long long MOD = 1000000007; //const long long MOD = 998244353; using namespace std; ll dp[3005][3005]; // dp[i][j] i番目(0,1,..i-1)まで見て、j個閉じている場合の危険度の最小値 int main(int argc, char* argv[]) { int n; scanf("%d%", &n); vector A(n),S(n+1); int i,j; for(i=0; i a(n+1),b(n+1); const double eps=1e-6; for(j=0; j<=n; j++) { if(j==0) { for(i=0; i<=n; i++) { dp[i][j]=S[i]*S[i]; } } else { vector > z; // xの値, xより少し大きいところの直線のindex for(i=j; i<=n; i++) { { // for CHT a[i]=-2*S[i]; b[i]=dp[i-1][j-1]+S[i]*S[i]; while( 1 ) { if(z.empty()) { z.push_back(make_pair(-HUGE_VAL,i)); break; } else { double x0=z.back().first; int id0=z.back().second; double tmp=-(double)(b[i]-b[id0])/(a[i]-a[id0]); if(tmpj) { ll tmp=0; if(!z.empty()) { int k=lower_bound(z.begin(), z.end(), make_pair((double)S[i]+eps,-INF))-z.begin(); if(k>0) { k--; int id=z[k].second; tmp=a[id]*S[i]+b[id]; } } dp[i][j]=tmp+S[i]*S[i]; } } } } for(i=0; i