1911: [Apio2010]特别行动队
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3191 Solved: 1450
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4
-1 10 -20
2 2 3 4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
Source
【思路】
斜率优化。
设f[i]表示将前i个分组的最优值,则有转移方程式:
f[i]=max{ f[j]+a*(C[i]-C[j])^2+b*(C[i]-C[j])+c }
经过化简得到:
f[i]=max{ (f[j]+a*C[j]^2-b*C[j])-2*a*C[i]*C[j] } + a*C[i]^2+b*C[i]+c
单调队列维护上凸包即可。
【代码】
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 5 typedef long long LL; 6 const int N = 1000000+10; 7 struct point { LL x,y; 8 }q[N],now; 9 int n,a,b,c,L,R; LL C[N]; 10 11 LL cross(point a,point b,point c) { 12 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 13 } 14 void read(LL& x) { 15 char c=getchar(); while(!isdigit(c)) c=getchar(); 16 x=0; while(isdigit(c)) x=x*10+c-'0' , c=getchar(); 17 } 18 int main() { 19 scanf("%d%d%d%d",&n,&a,&b,&c); 20 for(int i=1;i<=n;i++) 21 read(C[i]) , C[i]+=C[i-1]; 22 for(int i=1;i<=n;i++) { 23 while(L<R && q[L].y-2*a*C[i]*q[L].x <= q[L+1].y-2*a*C[i]*q[L+1].x) L++; 24 now.x=C[i]; 25 now.y=q[L].y-2*a*C[i]*q[L].x+2*a*C[i]*C[i]+c; 26 while(L<R && cross(q[R-1],now,q[R])<=0) R--; 27 q[++R]=now; 28 } 29 printf("%lld",q[R].y+b*C[n]-a*C[n]*C[n]); 30 return 0; 31 }