bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

 

1911: [Apio2010]特别行动队

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 3191  Solved: 1450
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

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 }
原文地址:https://www.cnblogs.com/lidaxin/p/5117768.html