[bzoj3675]序列分割
可以发现分割的顺序并不会影响答案,也就是一个划分的问题
dp,用f[i][j]表示前i个数划分为j段的答案,那么方程是$f[i][j]=max(f[k][j-1]+(S[i]-S[k])*(S[n]-S[i])$,滚动+斜率优化即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define y(i) (g[i]-a[i]*a[n]) 5 int n,k,x,l,r,q[N]; 6 long long a[N],g[N],f[N]; 7 double xl(int i,int j){ 8 return 1.0*(y(i)-y(j))/(a[i]-a[j]); 9 } 10 int main(){ 11 scanf("%d%d",&n,&k); 12 for(int i=1;i<=n;i++){ 13 scanf("%d",&x); 14 a[i]=a[i-1]+x; 15 } 16 for(int i=0;i<=k;i++){ 17 l=r=1; 18 for(int j=1;j<=n;j++){ 19 while ((l<r)&&(xl(q[l],q[l+1])>-a[j]))l++; 20 x=q[l]; 21 f[j]=g[x]+(a[j]-a[x])*(a[n]-a[j]); 22 while ((l<r)&&(xl(q[r-1],q[r])<xl(q[r],j)))r--; 23 if (a[j]!=a[j-1])q[++r]=j; 24 } 25 memcpy(g,f,sizeof(f)); 26 } 27 printf("%lld",f[n]); 28 }