版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/83384165
Time Limit: 4 Sec Memory Limit: 64 MB
Description
Input
Output
HINT
题目分析
斜率优化DP–详解
首先容易想到一个简单的
算法
表示前
个士兵分组能得到的最大战斗力
然后把平方拆开,移项
以
为
,
为
,
为斜率进行斜率优化即可
注意此题所求是最大值,单调队列维护的是斜率单调递减的上凸壳
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
typedef double dd;
#define sqr(x) ((x)*(x))
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=2000010;
lt n,a,b,c;
lt sum[maxn],dp[maxn];
int q[maxn],ll,rr;
lt qans(int i,int j){ return dp[j]+a*sqr(sum[j])-b*sum[j]-2*a*sum[i]*sum[j]+a*sqr(sum[i])+b*sum[i]+c;}
dd calc(int j1,int j2)
{
lt ty=(dp[j2]+a*sqr(sum[j2])-b*sum[j2])-(dp[j1]+a*sqr(sum[j1])-b*sum[j1]);
lt tx=sum[j2]-sum[j1];
return (dd)ty/(dd)tx;
}
int main()
{
n=read();a=read();b=read();c=read();
for(int i=1;i<=n;++i)
{
int x=read();
sum[i]=sum[i-1]+x;
}
ll=rr=1;
for(int i=1;i<=n;++i)
{
while( ll<rr && calc(q[ll],q[ll+1]) >= 2*a*sum[i] ) ++ll;
dp[i]=qans(i,q[ll]);
while( ll<rr && calc(q[rr-1],q[rr]) <= calc(q[rr],i) ) --rr;
q[++rr]=i;
}
printf("%lld",dp[n]);
return 0;
}