【BZOJ】1911: [Apio2010]特别行动队(斜率优化dp)
题目
传送门:QWQ
分析
用$ dp[i] $ 表示前 i 个人组成的战斗力之和
然后显然$ dp[i]=Max ( dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c ) $
然后就是斜率优化dp的套路,设个k比j优...........
然后对最后得出的式子搞斜率优化(太长了懒得写)
代码
#include <bits/stdc++.h> using namespace std; const int maxn=1000005; typedef long long ll; ll dp[maxn],sum[maxn],x[maxn], a, b, c; int que[maxn], L, R; inline double slope(int j,int k){ return (double)((dp[j]+a*sum[j]*sum[j]-b*sum[j]-dp[k]-a*sum[k]*sum[k]+b*sum[k]))/(double)(sum[j]-sum[k])/(double)(2*a); } ll sqr(ll a){return a*a;}; int main(){ int n; scanf("%d%lld%lld%lld",&n,&a,&b,&c); for(int i=1;i<=n;i++) scanf("%lld",&x[i]),sum[i]=sum[i-1]+x[i]; for(int i=1;i<=n;i++){ while(L<R && slope(que[L],que[L+1])<(double)(sum[i])) L++; int j=que[L];//printf("---- %d %lf %lf %lf\n",j,slope(1,2),slope(2,3),slope(3,4)); dp[i]=dp[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c; while(L<R && slope(que[R-1],que[R])>slope(que[R],i)) R--; que[++R]=i; } printf("%lld\n",dp[n]); return 0; }