題意
給出一個常數a,b,c和數列{
找到一種分組方案使貢獻和最大
解題報告
前兩天寫的沒來得及寫博客現在找不到推式子的草稿紙了…只好再推一遍…
斜率優化
設置狀態
轉移時若有
整理,得
局勢漸漸明朗了…右邊可以看做斜率的形式,左邊與j,k無關
因爲求最大,其實就是維護右邊的斜率單調不減,單調隊列維護一下就好了
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000005
#define LL long long
#define inf 1e18
using namespace std;
int n,q[N];
LL sum[N],a,b,c,f[N];
inline double calc(int x,int y){return (double)(f[x]-f[y]+a*(sum[x]*sum[x]-sum[y]*sum[y])+b*(sum[y]-sum[x]))/(double)(2*a*(sum[x]-sum[y]));}
int main(){
scanf("%d%lld%lld%lld",&n,&a,&b,&c);
for(int i=1;i<=n;++i) scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
int l=0,r=0;
for(int i=1;i<=n;++i){
while(l<r&&calc(q[l],q[l+1])<sum[i]) ++l;
LL tmp=sum[i]-sum[q[l]];
f[i]=f[q[l]]+a*tmp*tmp+b*tmp+c;
while(l<r&&calc(q[r-1],q[r])>calc(q[r],i)) --r;
q[++r]=i;
}
printf("%lld\n",f[n]);
return 0;
}