可以证明选的顺序对答案没有影响
于是有转移方程
变形得到
我们令
另外 , 写之前最好画图考虑细节
最大值维护上凸包,斜率是负数 , 所以图大概是这样
然后树形结合来写
#include<bits/stdc++.h>
#define N 100050
#define M 205
#define y(k,x) (f[x][k-1]-s[x]*s[x])
#define LL long long
using namespace std;
LL f[N][M]; int from[N][M];
int n,k,val[N],q[N]; LL s[N];
double K(int now,int i,int j){
if(s[i]==s[j]) return 1e18;
return (y(now,j)-y(now,i))*1.0/(s[j]-s[i])*1.0;
}
void dfs(int i,int j){
if(j==0) return;
i=from[i][j]; printf("%d ",i); dfs(i,j-1);
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&val[i]); s[i]=(LL)s[i-1]+val[i];
}
for(int i=1;i<=k;i++){
int l=1,r=0;
for(int j=1;j<=n;j++){
while(l<r && K(i,q[l],q[l+1]) >= -s[j]) l++;
f[j][i] = f[q[l]][i-1] + (LL)s[q[l]] * (s[j]-s[q[l]]);
from[j][i] = q[l];
while(l<r && K(i,q[r],j) >= K(i,q[r-1],q[r])) r--;
q[++r] = j;
}
}printf("%lld\n",f[n][k]); dfs(n,k);
return 0;
}