[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 }
View Code

 

posted @ 2019-10-07 06:16  PYWBKTDA  阅读(165)  评论(0编辑  收藏  举报