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

    bzoj1911 [Apio2010]特别行动队

    题意:

    n个人,拆成若干个队。设x等于队里每个人战斗力之和,则这个队战斗力为ax2+bx+c(a,b,c已知)。求所有队战斗力总和最大多少。

    题解:

    方程:f[i]=max{f[j]+(sum[i]-sum[j])2*a+(sum[i]-sum[j])*b+c|1≤j<i},将方程化简可以得到只要f[j]-f[k]+a*(sum[j])2-a*(sum[k])2+b*(sum[k]-sum[j]))/(2*a*(sum[j]-sum[k])>sum[i]则说明用j递推比用k递推更优。同时这个式子是一个分式,可以看成一条线段的斜率,而斜率又满足这样一个性质:线段AB斜率<线段BC斜率<线段CD斜率,则线段AB斜率<AC斜率<AD斜率。于是我们可以用一个单调队列满足每两项的f[j]-f[k]+a*(sum[j])2-a*(sum[k])2+b*(sum[k]-sum[j]))/(2*a*(sum[j]-sum[k])单调递增,每次用队头更新(因为队头到其他点的斜率肯定大于sum[i],最优)。注意单调队列的队头是l那一边。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(long long i=j;i<=k;i++)
     5 using namespace std;
     6 
     7 long long n,a,b,c,l,r,q[1000010],sum[1000010],f[1000010];
     8 inline long long sqr(long long a){return a*a;}
     9 inline double calc(long long a1,long long a2){
    10     return (double)(f[a1]-f[a2]+a*sqr(sum[a1])-a*sqr(sum[a2])+b*(sum[a2]-sum[a1]))/(double)(2*a*(sum[a1]-sum[a2]));
    11 }
    12 int main(){
    13     scanf("%lld%lld%lld%lld",&n,&a,&b,&c); 
    14     sum[0]=0; inc(i,1,n){long long a1;scanf("%lld",&a1); sum[i]=sum[i-1]+a1;}
    15     l=r=1;
    16     inc(i,1,n){
    17         while(l<r&&calc(q[l],q[l+1])<sum[i])l++;
    18         long long a1=q[l]; f[i]=f[a1]+sqr(sum[i]-sum[a1])*a+(sum[i]-sum[a1])*b+c;
    19         while(l<r&&calc(q[r-1],q[r])>calc(q[r],i))r--; q[++r]=i;
    20     }
    21     printf("%lld",f[n]);
    22     return 0;
    23 }

     

    20160320

  • 相关阅读:
    Django基础二之URL路由系统
    Django基础一之web框架的本质
    HTTP协议超级详解
    动态规划-背包问题
    java 中对象比较大小
    排序算法
    泛型
    打jar包和使用jar包
    Mongodb中Sharding集群
    linux时间同步,ntpd、ntpdate
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5656769.html
Copyright © 2011-2022 走看看