洛谷P3628 [APIO2010]特别行动队 斜率优化

裸题,注意队列下标不要写错

Code:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2000000 + 3;
long long f[maxn], sum[maxn], a, b, c;
int n, q[maxn];
inline double re_x(int i){ return sum[i]; };
inline double re_y(int i){ return f[i] + a * sum[i] * sum[i] - b * sum[i]; }
inline double re_slope(int i,int j){ return (re_y(i) - re_y(j)) / (re_x(i) - re_x(j)); }
int main()
{

    freopen("input.txt","r",stdin);
    scanf("%d",&n);
    scanf("%lld%lld%lld",&a,&b,&c);
    for(int i = 1;i <= n; ++i)scanf("%lld",&sum[i]), sum[i] += sum[i - 1];
    int head = 0, tail = 0;
    for(int i = 1;i <= n; ++i)
    {
        while(head < tail && re_slope(q[head], q[head + 1]) > sum[i] * 2 * a) ++ head;
        f[i] = f[q[head]] + a * (sum[i] - sum[q[head]]) * (sum[i] - sum[q[head]]) + b * (sum[i] - sum[q[head]]) + c;
        while(head < tail && re_slope(i, q[tail - 1])  >re_slope(q[tail - 1], q[tail])) -- tail;
        q[++tail] = i;
    }
    printf("%lld",f[n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值