// #pragma GCC target("avx") // CPU 処理並列化 // #pragma GCC optimize("O3") // CPU 処理並列化 // #pragma GCC optimize("unroll-loops") // 条件処理の呼び出しを減らす #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const long long mod=1000000007; const long long inf=mod*mod; const long long d2=(mod+1)/2; const double EPS=1e-10; const double INF=1e+10; const double PI=acos(-1.0); const int C_SIZE = 3100000; const int UF_SIZE = 210000; namespace{ long long fact[C_SIZE]; long long finv[C_SIZE]; long long inv[C_SIZE]; long long Comb(int a,int b){ if(a +EPS) ? +1 : 0; } int UF[UF_SIZE]; void init_UF(int n){ for(int i=0;iUF[b])swap(a,b); UF[a]+=UF[b];UF[b]=a; } } // ここから編集しろ struct LiChaoTree{ typedef long long vint; typedef long long zint; typedef pair F; static const int seg_sz=4096; static const vint inf=mod*mod; static const zint xinf=mod; vectorx; F segtree[seg_sz*2]; vint func(F a,vint x){ return a.first*x+a.second; } void add_line(int a,int b,int c,F f){ if(segtree[c]==make_pair((vint)0,inf)){ segtree[c]=f; return; } int m=(a+b)/2; zint lx=x[a]; zint mx=x[m]; zint rx=x[b-1]; vint ly1=func(segtree[c],lx); vint my1=func(segtree[c],mx); vint ry1=func(segtree[c],rx); vint ly2=func(f,lx); vint my2=func(f,mx); vint ry2=func(f,rx); if(ly1<=ly2&&ry1<=ry2){ return; } if(ly1>ly2&&ry1>ry2){ segtree[c]=f; return; } if(my1>my2){ swap(segtree[c],f); if(ly1>ly2){ add_line(m,b,c*2+1,f); }else{ add_line(a,m,c*2,f); } return; } if(ly1>ly2){ add_line(a,m,c*2,f); }else{ add_line(m,b,c*2+1,f); } } void add_line(int a,int b,int c,int d,int e,F f){ if(d<=a||b<=c)return; if(c<=a&&b<=d){ add_line(a,b,e,f); return; } add_line(a,(a+b)/2,c,d,e*2,f); add_line((a+b)/2,b,c,d,e*2+1,f); } vint query(zint X){ int zx=lower_bound(x.begin(),x.end(),X)-x.begin(); zx+=seg_sz; vint ret=inf; while(zx){ ret=min(ret,func(segtree[zx],X)); zx/=2; } return ret; } void add_line(F a){ add_line(0,seg_sz,1,a); } void add_line(F a,zint b,zint c){ // add [b,c) int l=lower_bound(x.begin(),x.end(),b)-x.begin(); int r=lower_bound(x.begin(),x.end(),c)-x.begin(); if(l>=r)return; add_line(0,seg_sz,l,r,1,a); } void init(vectorX){ x=vector(seg_sz,xinf); for(int i=0;ix; for(int j=0;j<=a;j++){ x.push_back(S[j]); } lc.init(x); for(int j=0;i+j<=a+1;j++){ if(i!=1||j==0)lc.add_line(make_pair(-2*S[i+j-1],S[i+j-1]*S[i+j-1]+dp[i+j-1][j])); long long tmp=lc.query(S[i+j-1]); dp[i+j][j]=tmp+S[i+j-1]*S[i+j-1]; } } for(int i=1;i<=a;i++){ printf("%lld\n",dp[a+1][i]); } }