## [APIO2014]序列分割 题解

```#include<iostream>
#include<cstdio>
using namespace std;

const int maxn = 100005;
const int maxm = 205;
int n, m, pre[maxm][maxn], q[maxn];
long long int s[maxn], dp[maxm][maxn];

void do_it(int x) {
int ll=1, rr=0, i, y, z;
for(i=x-1; i <= n; i++) {
y=q[ll]; z=q[ll+1];
while(ll < rr &&
((dp[x-1][y]-s[y]*s[y]) - (dp[x-1][z]-s[z]*s[z])
< s[i]*(s[z]-s[y])
|| s[z] == s[y])
) {
ll++;
y=q[ll]; z=q[ll+1];
}
if(ll <= rr) {
y=q[ll];
dp[x][i] = dp[x-1][y]+s[y]*(s[i]-s[y]);
pre[x][i]=y;
//cout<<ll<<' '<<rr<<';'<<y<<' '<<i<<endl;
//cout<<dp[x][i]<<endl;
}
y=q[rr-1]; z=q[rr];
while(ll < rr &&
((((dp[x-1][y]-s[y]*s[y]) - (dp[x-1][z]-s[z]*s[z]) )*(s[i]-s[z])
> ((dp[x-1][z]-s[z]*s[z]) - (dp[x-1][i]-s[i]*s[i]) ) *(s[z]-s[y])
&& s[z] != s[y]) || s[i] == s[z])
) {
rr--;
y=q[rr-1]; z=q[rr];
}
rr++;
q[rr]=i;
}
return;
}

int main() {
int i, t;
cin>>n>>m;
m++;
for(i=1; i <= n; i++) {
cin>>s[i]; s[i]+=s[i-1];
}

for(i=2; i <= m; i++) do_it(i);// cout<<endl;

cout<<dp[m][n]<<endl;
t=n;
for(i=m; i >= 2; i--) {
cout<<pre[i][t]<<' ';
t=pre[i][t];
}
cout<<endl;
return 0;
}```

0条评论