bzoj1911 [Apio2010]特别行动队
Description
Input
Output
Sample Input
4
-1 10 -20
2 2 3 4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
正解:斜率优化。
很显然的斜率优化。我们可以很容易得到一个转移方程:f[i]=max(f[j]+a(p[i]-p[j])^2+b(p[i]-p[j])+c),其中p[i]为前缀和。我们把式子拆开以后就会发现这是个斜率优化的套路公式。。那么我们维护一个下凸包。其中y[i]=f[i]+a*p[1]*p[1]-b*p[1],x[i]=2*a*p[i],斜率为p[i]。那么这道题就能以O(n)的复杂度被解决了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (1000010) 15 #define il inline 16 #define RG register 17 #define int long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 int f[N],p[N],x[N],y[N],que[N],n,a,b,c,st,ed; 23 24 il int gi(){ 25 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 26 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 27 } 28 29 il double getk(RG int i,RG int j){ return 1.0*(y[i]-y[j])/(x[i]-x[j]); } 30 31 il void work(){ 32 n=gi(),a=gi(),b=gi(),c=gi(); 33 for (RG int i=1;i<=n;++i) p[i]=gi()+p[i-1]; 34 st=ed=1,que[++ed]=1,f[1]=a*p[1]*p[1]+b*p[1]+c; 35 y[1]=f[1]+a*p[1]*p[1]-b*p[1],x[1]=2*a*p[1]; 36 for (RG int i=2;i<=n;++i){ 37 while (st<ed && p[i]>getk(que[st],que[st+1])) st++; 38 f[i]=a*p[i]*p[i]+b*p[i]+c+y[que[st]]-x[que[st]]*p[i]; 39 y[i]=f[i]+a*p[i]*p[i]-b*p[i],x[i]=2*a*p[i]; 40 while (st<=ed && getk(que[ed-1],que[ed])>getk(que[ed],i)) ed--; 41 que[++ed]=i; 42 } 43 printf("%lld\n",f[n]); return; 44 } 45 46 main(){ 47 File("team"); 48 work(); 49 return 0; 50 }