题目描述
题解
感觉有点不在状态。。。
转移方程:
f[i][j]=max{f[i−1][k]+(s[j]−s[k])∗(s[n]−s[j])}
显然可以斜率优化。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
const int max_n=1e5+5;
int n,m,head,tail;
int q[max_n];
LL x,f[max_n],g[max_n],s[max_n];
inline LL K(int k){return s[k];}
inline LL B(int k){return g[k]-s[k]*s[n];}
inline LL Y(int j,int k){return K(k)*s[j]+B(k);}
inline bool cmp(int x1,int x2,int x3){
LL w1=(K(x1)-K(x3))*(B(x2)-B(x1));
LL w2=(K(x1)-K(x2))*(B(x3)-B(x1));
return w1>=w2;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%lld",&x),s[i]=s[i-1]+x;
for (int i=1;i<=m;++i){
head=tail=0;
for (int j=0;j<=n;++j){
while (head<tail&&Y(j,q[head])<=Y(j,q[head+1])) head++;
f[j]=Y(j,q[head])+s[j]*s[n]-s[j]*s[j];
while (head<tail&&cmp(j,q[tail-1],q[tail])) tail--;
q[++tail]=j;
}
for (int j=0;j<=n;++j) g[j]=f[j]/*,printf("%d %d:%d\n",i,j,g[j])*/;
}
LL ans=0;
for (int i=1;i<n;++i) ans=max(ans,g[i]);
printf("%lld\n",ans);
}