• [APIO2010]特别行动队


    洛咕

    题意:(N(N<=1000000))个士兵,每个士兵的战斗值为(x_i),将士兵分成若干批,设每一批的战斗值之和为t,每一批的战斗力(x'=at^2+bt+c),a(保证负数),b,c均为给定常数,求最大战斗力.

    (f[i])表示将前i个士兵分成若干批的最大战斗力,则有(f[i]=f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c)

    (k<j)且j比k更优,即

    (f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c>f[k]+a(sum[i]-sum[k])^2+b(sum[i]-sum[k])+c)

    整理一下上式得到,

    (frac{f[j]+sum[j]^2-f[k]-sum[k]^2}{sum[j]-sum[k]}>2asum[i]+b)

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    const int N=1000005;
    int n,a,b,c,l,r,q[N];LL sum[N],f[N];
    inline double check(int x,int y){return 1.0*(f[x]+a*sum[x]*sum[x]-b*sum[x]-f[y]-a*sum[y]*sum[y]+b*sum[y])/(sum[x]-sum[y]);}
    int main(){
        n=read(),a=read(),b=read(),c=read();
        for(int i=1;i<=n;i++){int x=read();sum[i]=sum[i-1]+x;}
        for(int i=1;i<=n;i++){
    		while(l<r&&check(q[l+1],q[l])>=2*a*sum[i])l++;
    		f[i]=f[q[l]]+a*(sum[i]-sum[q[l]])*(sum[i]-sum[q[l]])+b*(sum[i]-sum[q[l]])+c;
    		while(l<r&&check(q[r],q[r-1])<=check(i,q[r]))r--;
    		q[++r]=i;
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
    
    
  • 相关阅读:
    mysql新建用户的方法
    工具网站
    如何做好站内锚文本?
    js 创建对象与继承
    js tips
    js作用域链 js没有块级作用域
    css
    instanceof
    问题
    传递,引用副本传递
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11007456.html
Copyright © 2020-2023  润新知