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

斜率优化DP裸题,DP方程很简单就不给了

优化一下,整理式子成y=kx+b的形式

发现x单调递增,斜率k单调递减,用一个队列维护凸包就行啦

f[i]和b成正比,而f[i]期望最大值,所以维护上凸包

#include <cstdio>
#include <algorithm>
#include <cstring>
#define il inline
#define ll long long
#define N 1001000
using namespace std;
//re
int n;
ll A,B,C;
int que[N];
ll f[N],d[N],sum[N];
int gc()
{
    int rett=0,fh=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    while(c>='0'&&c<='9'){rett=(rett<<3)+(rett<<1)+c-'0';c=getchar();}
    return rett*fh;
}
il ll yy(int i){return f[i]+A*sum[i]*sum[i]-B*sum[i]+C;}
il ll xx(int i){return sum[i];}

int main()
{
    n=gc(),A=gc(),B=gc(),C=gc();
    for(int i=1;i<=n;i++) d[i]=gc();
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+d[i];
    int hd=1,tl=1;
    for(int i=1;i<=n;i++)
    {
        while(hd+1<=tl&&yy(que[hd])-(ll)2*A*sum[i]*xx(que[hd]) <= yy(que[hd+1])-(ll)2*A*sum[i]*xx(que[hd+1]))
            hd++;
        f[i]=yy(que[hd])-(ll)2*A*sum[i]*xx(que[hd])+A*sum[i]*sum[i]+B*sum[i];
        while(hd+1<=tl&& (yy(i)-yy(que[tl]))*(xx(que[tl])-xx(que[tl-1])) >= (yy(que[tl])-yy(que[tl-1]))*(xx(i)-xx(que[tl])))
            tl--;
        que[++tl]=i;
    }
    printf("%lld\n",f[n]);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/guapisolo/article/details/82630757