题面

题意体面中写得很明确, 应该不用我说了, 方差的概念在初中人教版九年级数学中有所提到, 没有上过初中的同学们可以左转百度.

将序列拆为几段求最值, 我们考虑用dp来实现.

先推一下式子, 令方差为\(v\), \(r\)为某一段路径的长度, \(\overline r\)为这\(m\)条路径长度的平均数.

则有:

\[\begin{aligned}
v &= \frac{\sum_{i=1}^{m}(\overline r - r_i)^2}{m}\\
&= \frac{\sum_{i=1}^{m}r_i^2 + m * (\overline r)^2 - 2 * (\overline r) * \sum_{i=1}^{m}r_i}{m}\\
&= \frac{\sum_{i=1}^{m}r_i^2 + m * (\frac{\sum_{i=1}^{m}r_i}{m})^2 - 2 * \frac{(\sum_{i=1}^{m}r_i)^2}{m}}{m}\\
&=- \frac{(\sum_{i=1}^{m}r_i)^2}{m ^ 2} + \frac{\sum_{i=1}^{m}r_i^2}{m}
\end{aligned}
\]

答案所求为\(v * m ^ 2\), 所以:

\[\begin{aligned}
v * m ^ 2 &= m * \sum_{i=1}^{m}r_i^2 - (\sum_{i=1}^{m}r_i) ^ 2\\
\end{aligned}
\]

我们发现\((\sum_{i=1}^{m}r_i) ^ 2\)是一个定值, 也就是总路径长度的平方, 所以我们只需要求前面那个数就可以了, 用前缀和先处理一下, 即\(S_i\)表示1 ~ i的路径的长度.

我们设\(f[i][k]\)表示前\(i\)段路花\(k\)天走的最小花费, 所以我们可以得到状态转移方程:

\[f[i][k] = min(f[i][k], f[j][k - 1] + (sum[j] - sum[i])^2)
\]

还是老套路, 设对\(i\)点选\(t\)(\(t\) > \(j\))转移比选\(j\)转移更优, 则有:

\[\begin{aligned}
f[t][k - 1] + (sum[t] - sum[i])^2 &< f[j][k - 1] + (sum[j] - sum[i]) ^ 2\\
(f[t][k - 1] + sum[t] ^ 2) - (f[j][k - 1] + sum[j] ^ 2) &< 2 * sum[i] * (sum[t] - sum[j])\\
\frac{(f[t][k - 1] + sum[t] ^ 2) - (f[j][k - 1] + sum[j] ^ 2)}{2 * (sum[t] - sum[j])} &< sum[i]
\end{aligned}
\]

由此可知道我们需要维护一个下凸包, 不信的话选三个点试一下就可以发现了, 然后愉快的推式子时间又结束了, 下面是大家喜(shen)闻(wu)乐(tong)见(jue)的\(Coding Time\)...

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#define N 3005
using namespace std; int n, m, sum[N], q[N], l, r;
long long f[N], g[N]; inline int read()
{
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
} bool F_check(int x, int y, int z) { return 1ll * (g[y] - g[x] + sum[y] * sum[y] - sum[x] * sum[x]) < 1ll * 2 * z * (sum[y] - sum[x]); } bool S_check(int x, int y, int z) { return (g[y] - g[x] + sum[y] * sum[y] - sum[x] * sum[x]) * (sum[z] - sum[y]) > (g[z] - g[y] + sum[z] * sum[z] - sum[y] * sum[y]) * (sum[y] - sum[x]); } int main()
{
n = read(); m = read();
for(int i = 1; i <= n; i++) { sum[i] = read(); sum[i] += sum[i - 1]; g[i] = 1ll * sum[i] * sum[i]; }
for(int k = 1; k < m; k++)
{
l = 1; r = 0; q[++r] = k;
for(int i = k + 1; i <= n; i++)
{
while(l < r && F_check(q[l], q[l + 1], sum[i])) l++;
f[i] = g[q[l]] + 1ll * (sum[i] - sum[q[l]]) * (sum[i] - sum[q[l]]);
while(l < r && S_check(q[r - 1], q[r], i)) r--;
q[++r] = i;
}
for(int i = 1; i <= n; i++) g[i] = f[i];
}
printf("%lld\n", m * f[n] - sum[n] * sum[n]);
return 0;
}

不知道交了多少遍才AC的菜鸡我

[luogu4072] 征途的更多相关文章

  1. bzoj4518/luogu4072 征途(斜率优化dp)

    首先推一波公式: 设f[t][i]为第t天以i为结尾,这时已经算了的最小公差$*m^2$ 设s[i]为1到i的和 $$f[t][i]=min\{f[t-1][j]+m*(s[i]-s[j]-\frac ...

  2. [luogu4072][bzoj4518][SDOI2016]征途【动态规划+斜率优化】

    题目分析 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路 ...

  3. Java 征途:行者的地图

    前段时间应因缘梳理了下自己的 Java 知识体系, 成文一篇望能帮到即将走进或正在 Java 世界跋涉的程序员们. 第一张,基础图 大约在 2003 年我开始知道 Java 的(当时还在用 Delph ...

  4. 征途 bzoj 4518

    征途(1s 256MB)journey [问题描述] Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天 ...

  5. seL4之hello-3征途

    seL4之hello-3征途 回顾上周 了解seL4的启动流程和初始化线程 了解seL4的几种内核对象和权能机制 完成hell0-2的运行. 补充上周 1.找到根任务(初始化线程)的创建具体的位置(那 ...

  6. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  7. 【BZOJ-4518】征途 DP + 斜率优化

    4518: [Sdoi2016]征途 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 230  Solved: 156[Submit][Status][ ...

  8. [转]Java 征途:行者的地图

    前段时间应因缘梳理了下自己的 Java 知识体系, 成文一篇望能帮到即将走进或正在 Java 世界跋涉的程序员们. 第一张,基础图 大约在 2003 年我开始知道 Java 的(当时还在用 Delph ...

  9. BZOJ4518: [Sdoi2016]征途

    Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜 ...

随机推荐

  1. oracleHelper 操作帮助类

    using System; using System.Configuration; using System.Data; using System.Collections; using Oracle. ...

  2. JavaSE Collection集合

    集合:是java中提供的一种容器,可以用来存储多个对象.可是我们前面学习的数组也是可以保存多个对象的,为什么还要提供集合容器呢?集合和数组它们有啥区别呢? 数组的长度是固定的.一旦创建完成不能改变长度 ...

  3. Bell(矩阵快速幂+中国剩余定理)

    Bell Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status  ...

  4. Java static和final

    java提高篇(七)-----关键字static static 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中static表示“全局”或者“静 ...

  5. HDU4662(SummerTrainingDay03-B)

    MU Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  6. PHP 协程最简洁的讲解

    协程,又称微线程,纤程.英文名Coroutine.协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执 ...

  7. CentOS7上搭建LDAP-PDC并且将windows 2008 R2加入LDAP-PDC域

    由于测试原因,要涉及到将windows机器加入到ldap域,所以查看各种文档进行ldap-pdc域的搭建,并成功将windows 2008r2加入到ldap-pdc域中.下面简单记录一下搭建过程 Li ...

  8. SpringMVC—Struts2拦截器学习网址整理

    引自:http://blog.csdn.net/wp1603710463/article/details/49982683 SpringMVC—Struts2拦截器学习网址整理 最近项目中遇到权限相关 ...

  9. 如何在Vue中建立全局引用或者全局命令

    1 一般在vue中,有很多vue组件,这些组件每个都是一个文件.都可能需要引用到相同模块(或者插件).我们不想每个文件都import 一次模块. 如果是基于vue.js编写的插件我们可以用 Vue.u ...

  10. JMeter初体验

    Meter是开源软件Apache基金会下的一个性能测试工具,用来测试部署在服务器端的应用程序的性能. 1.JMeter下载和安装 JMeter可以在JMeter的官方网站下载,目前能下载的是JMete ...