zoukankan      html  css  js  c++  java
  • [bzoj1911][Apio2010]特别行动队

    Description

    n个元素x_i
,可以将n个元素分成多组,每组的元素编号必须是连续的.

    设每组的x_i
x,则每组的价值公式为ax^2+bx+c.

    求最大价值和.

    Input

    输入由三行组成。

    第一行包含一个整数n,表示士兵的总数.

    第二行包含三个整数a,b,c,价值公式中各项的系数.

    第三行包含n个用空格分隔的整数x_i
.

    Output

    输出一个整数,表示最大价值和。

    Sample Input

    4

    -1 10 -20

    2 2 3 4

    Sample Output

    9

    HINT

     1;leq;n;leq;10^6,-5;leq;a;leq;-1,|b|;leq;10^7,|c|;leq;10^7,1;leq;x_i;leq;100。

    Solution

    f[i]表示前i个的最大价值和,

    f[i]=max{f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c}(j<i).

    这样是O(n^2)的,显然过不了,所以考虑斜率优化.

    k>jf[i]_k>f[i]_j时,

    f[i]_j=f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c

    f[i]_k=f[k]+a(sum[i]-sum[k])^2+b(sum[i]-sum[k])+c

    尽量将i,j分离:

    g[i]=a;	imes;sum[i]^2+b;	imes;sum[i]+c,

    h[j]=f[j]+a;	imes;sum[j]^2-b;	imes;sum[j]

    f[i]_j=g[i]+h[j]-2a;	imes;sum[i];	imes;sum[j],

    f[i]_k=g[i]+h[k]-2a;	imes;sum[i];	imes;sum[k].

    f[i]_k>f[i]_j的前提条件是

    g[i]-g[i]+h[k]-h[j]-2a;	imes;sum[i](sum[k]-sum[j])>0.

    整理得,frac{h[k]-h[j]}{sum[k]-sum[j]}>2a;	imes;sum[i].

     T(j_1,j_2)=frac{g[j_2]-g[j_1]}{sum[j_2]-sum[j_1]},

    则队列中的元素满足T(j_1,j_2)>T(j_2,j_3)>...

    (若存在T(j_{i-1},j_i)<T(j_i,j_{i+1}),因为sum[i]是递增的,所以j_{i+1}j_i优,即j_i可以删去),

    所以每次取元素时,将满足T(j_i,j_{i+1})>2a;	imes;sum[i]j_i出队(因为j_{i+1}j_i优),然后取队首为j.

    #include<set> 
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 1000001
    using namespace std;
    typedef long long ll;
    ll f[N],s[N],q[N],a,b,c,n,h,t;
    inline ll sqr(ll k){
        return k*k;
    }
    inline ll y(ll k){
        return a*sqr(s[k])+b*s[k]+c;
    }
    inline ll g(ll k){
        return f[k]+a*sqr(s[k])-b*s[k];
    }
    inline ll func(ll k){
        return a*sqr(k)+b*k+c;
    } 
    inline double cmp(ll p,ll q){
        return (double)(g(q)-g(p))/(double)(s[q]-s[p]);
    }
    inline void init(){
        scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
        for(ll i=1;i<=n;i++){
            scanf("%lld",&s[i]);
            s[i]+=s[i-1];
        }
        for(ll i=1,k;i<=n;i++){
            k=(a<<1)*s[i];
            while(h<t&&cmp(q[h],q[h+1])>k) h++;
            f[i]=f[q[h]]+func(s[i]-s[q[h]]);
            while(h<t&&cmp(q[t],i)>cmp(q[t-1],q[t]))
                t--;
            q[++t]=i;
        }
        printf("%lld
    ",f[n]);
    }
    int main(){
        freopen("commando.in","r",stdin);
        freopen("commando.out","w",stdout);
        init();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

  • 相关阅读:
    Django ORM操作及进阶
    Django ORM字段和字段参数
    Django视图系统
    Django路由系统
    Django模板语言
    Django项目创建及相关配置,在pycharm终端打印SQL语句,在Python脚本中调用Django环境
    SQLALchemy之ORM操作
    SQLALchemy之介绍,基本使用
    SQLAlchemy创建表和删除表
    线程的通信与协作:sleep、wait、notify、yield、join关系与区别
  • 原文地址:https://www.cnblogs.com/AireenYe/p/5934065.html
Copyright © 2011-2022 走看看