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

1911: [Apio2010]特别行动队

Time Limit: 4 Sec   Memory Limit: 64 MB
Submit: 3550   Solved: 1629
[ Submit][ Status][ Discuss]

Description

bzoj 1911: [Apio2010]特别行动队(斜率优化)_第1张图片

Input

Output

Sample Input

4
-1 10 -20
2 2 3 4

Sample Output

9

HINT

bzoj 1911: [Apio2010]特别行动队(斜率优化)_第2张图片

Source

[ Submit][ Status][ Discuss] 

题解:斜率优化DP

状态转移方程: f[i]=f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<cmath>  
#define ll long long   
#define N 1000003  
using namespace std;  
int n;
ll m,f[N],a,b,c,t[N],sum[N],q[N];  
ll K(int x)  
{  
    return -2*a*sum[x];  
}  
ll B(int x)  
{  
    return f[x]+a*sum[x]*sum[x]-b*sum[x];  
}   
ll calc(int x,int y)  
{  
    return c+b*sum[y]+a*sum[y]*sum[y]+K(x)*sum[y]+B(x);  
}  
bool pd(int x1,int x2,int x3)  
{  
    ll w1=(ll)(K(x3)-K(x2))*(B(x3)-B(x1));  
    ll w2=(ll)(K(x1)-K(x3))*(B(x2)-B(x3));
    //cout<<w1<<" "<<w2<<endl;  
    return w1>=w2;  
}  
int main()  
{  
    scanf("%d",&n);  
    scanf("%lld%lld%lld",&a,&b,&c);  
    for (int i=1;i<=n;i++)  
     {  
        scanf("%lld",&t[i]);  
        sum[i]=sum[i-1]+t[i]; 
        //cout<<t[i]<<endl; 
        //cout<<sum[i]<<endl; 
     }  
    int head=0,tail=0;  
    for (int i=1;i<=n;i++)  
    {  
        while (head<tail&&calc(q[head],i)<=calc(q[head+1],i))  
         head++;  
        f[i]=calc(q[head],i); //cout<<f[i]<<endl; 
        while (head<tail&&pd(q[tail],q[tail-1],i))  
         tail--;  
        tail++; q[tail]=i;  
    }  
    printf("%lld",f[n]);  
}  


你可能感兴趣的:(bzoj 1911: [Apio2010]特别行动队(斜率优化))