难度在于认识到顺序是没有关系的
斜率优化
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,K,Sum[100005],a[100005];
long long F[2][100005];
struct node{
long long k,b;
}stack[1000005];
double check(node a,node b){
return ((double)a.b-b.b)/(b.k-a.k);
}
int main(){
scanf("%d%d",&m,&K);
for (int i=1; i<=m; i++) {
int x;
scanf("%d",&x);
if (x) a[++n]=x;
}
for (int i=1; i<=n; i++) Sum[i]=Sum[i-1]+a[i];
for (int k=1; k<=K; k++){
for (int i=0; i<=n; i++) F[k%2][i]=0;
int head=1,tail=0;
for (int i=0; i<=n; i++){
node line=(node){Sum[i],F[(k-1)%2][i]-1ll*Sum[i]*Sum[i]};
while (tail-head>0 && check(stack[tail],stack[tail-1])>check(stack[tail],line)) tail--;
stack[++tail]=line;
while (tail-head>0 && check(stack[head],stack[head+1])<Sum[i]) head++;
F[k%2][i]=stack[head].k*Sum[i]+stack[head].b;
}
}
printf("%lld\n",F[K%2][n]);
return 0;
}