• bzoj 4518: [Sdoi2016]征途


    Description

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

    solution

    **这题拆开式子容易发现,要求的就是:

    [m*sum_{i=1}^{m}{xi^2}-sum^2 ]

    即分成 (m)段,每一段为 (xi^2),这不就是做过的题了吗?
    普遍的用斜率优化秒,本人蒟蒻,写的决策单调性,分治处理.**

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef long long ll;
    const int N=3005,inf=1e9;
    int n,m,a[N],sum[N],f[N][N];
    void solve(int l,int r,int sa,int se,int j){
       if(l>r)return ;
       int p=sa,mid=(l+r)>>1,tmp,val=inf;
       for(int i=sa;i<mid && i<=se;i++){
          tmp=f[i][j-1]+(sum[mid]-sum[i])*(sum[mid]-sum[i]);
          if(tmp<val)val=tmp,p=i;
       }
       f[mid][j]=val;
       solve(l,mid-1,sa,p,j);solve(mid+1,r,p,se,j);
    }
    void work()
    {
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
       for(int i=1;i<=n;i++)f[i][0]=inf;
       for(int i=1;i<=m;i++)
          solve(1,n,0,n,i);
       printf("%lld
    ",(ll)m*f[n][m]-(ll)sum[n]*sum[n]);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    __attribute__((noreturn))的用法
    selenium定位元素的方法
    zzz
    go语言的第一个helloworld
    mac eclipse 创建Java 工程
    Jmeter:图形界面压力测试工具
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    从Log4j迁移到LogBack的理由
    SLF4J和Logback日志框架详解
    security with restful
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7684408.html
Copyright © 2020-2023  润新知