zoukankan      html  css  js  c++  java
  • [BZOJ4518]征途

    4518: [Sdoi2016]征途

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

    Pine开始了从S地到T地的征途。
    从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。
    Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。
    Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。
    帮助Pine求出最小方差是多少。
    设方差是v,可以证明,v×m^2是一个整数。为了避免精度误差,输出结果时输出v×m^2。

    Input

    第一行两个数 n、m。
    第二行 n 个数,表示 n 段路的长度

    Output

     一个数,最小方差乘以 m^2 后的值

    Sample Input

    5 2
    1 2 5 8 6

    Sample Output

    36

    HINT

    1≤n≤3000,保证从 S 到 T 的总路程不超过 30000

    题解:

    推式子的感觉真刺激呀....

    我们复习一下方差的定义:数值与平均值之差的平方和的平均值

    设s[i]为前缀和,设X0是平均值,则X0=s[n]/m

    也就是说,V=((X1-X0)2+(X2-X0)2+......+(Xm-X0)2)/m

    由于答案是V*m2,所以我们不妨把m2直接带上.

    所以有:

    ans=((X1-X0)2+(X2-X0)2+......+(Xm-X0)2)*m

       =m*ΣXi2+m*X02*m-2*X0*m*ΣXi

       =m*ΣXi2+s[n]2-2*s[n]2

         =m*ΣXi2-s[n]2

    这样我们就找到了一个很简洁的表达式

    但是如果直接计算这个式子,你会发现推不出来,所以我们转化一下角度,转而计算ΣXi2的值.

    我们可以维护一个数组f[i][j],表示在第j段路结尾,第i次休息的时候最小的ΣXi2,那么答案就是m*f[m][n]-s[n]2

    那么f[i][j]=min{f[k][j-1]+(s[i]-s[k])2}.

    分析一下复杂度,Ο(m*n*n),如果是极限数据会变成30003,这样就要t了

    所以我们考虑优化,对于可能转移到i的2个位置k1与k2,k1优于k2的条件是什么?(公式恐惧症的同学不要跑啊......)

    f[k1][j-1]+(s[i]-s[k1])2<f[k2][j-1]+(s[i]-s[k2])2

    f[k1][j-1]-f[k2][j-1]<(s[i]-s[k2])2-(s[i]-s[k1])2

    f[k1][j-1]-f[k2][j-1]<s[i]2-2*s[i]*s[k2]+s[k2]2-(s[i]2-2*s[i]*s[k1]+s[k1]2)

    f[k1][j-1]-f[k2][j-1]<s[k2]2-s[k1]2-2*s[i]*s[k2]+2*s[i]*s[k1]

    f[k1][j-1]-f[k2][j-1]+s[k1]2-s[k2]2<2*s[i]*(s[k1]-s[k2])

    (f[k1][j-1]-f[k2][j-1]+s[k1]2-s[k2]2)/(s[k1]-s[k2])<2*s[i]

    所以我们用一个单调队列维护就行啦,剩下的维护判断就比较简单了~

    代码见下:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int N=3010;
    LL len[N],n,m,s[N],f[N][N];
    int q[N]; 
    inline int min(int a,int b){return a<b?a:b;}
    inline double k(int j,int k1,int k2)
    {
        double a=(double)(f[j-1][k1]-f[j-1][k2]+s[k1]*s[k1]-s[k2]*s[k2]);
        return a/(double)(s[k1]-s[k2]);
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%lld",&len[i]),s[i]=s[i-1]+len[i];
        for(int j=1;j<=n;j++)
            f[1][j]=s[j]*s[j];
        for(int i=2,h=1,t=1;i<=m;i++,h=1,t=1)
        {
            memset(q,0,sizeof(q));
            for(int j=1;j<=n;j++)
            {
                while(h<t&&k(i,q[h+1],q[h])<2*s[j])h++;
                f[i][j]=f[i-1][q[h]]+(s[j]-s[q[h]])*(s[j]-s[q[h]]);
                while(h<t&&k(i,j,q[t])<k(i,q[t],q[t-1]))t--;
                q[++t]=j;
            }
        }
        printf("%lld",m*f[m][n]-s[n]*s[n]);
    }
    BZOJ4815
    Progress is not created by contented people.
  • 相关阅读:
    Hadoop Yarn 框架原理及运作机制及与MapReduce比较
    模型驱动与属性驱动区别
    spark伪分布式的安装
    大数据集群的常见问题
    linux常用命令
    大数据集群ssh登录其他机器失败 RSA host key for zb03 has changed and you have requested strict checking. Host key verification failed.
    Python 地点转化为经纬度
    Hbase原理、基本概念、基本架构
    struts2的java.lang.NoSuchMethodException错误
    抽象工厂
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7008103.html
Copyright © 2011-2022 走看看