题面

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

将序列拆为几段求最值, 我们考虑用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. SpringBoot中动态加载(热部署)

    在常规的Java Web开发过程中,在修改完代码后,往往需要重启Tomcat来使得我们的修改生效,在SpringBoot中也需要从新启动SpringBoot来将修改部署.如果我们不希望重启tomcat ...

  2. Sql Server 与 MySql 在使用 update inner join 时的区别

    Sql Server -- 不使用别名 UPDATE tb_User SET tb_User.pass = '' FROM tb_User usr INNER JOIN tb_Address addr ...

  3. Java虚拟机 - 类加载机制

    [深入Java虚拟机]之四:类加载机制 类加载过程     类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下 ...

  4. java设计模式(一)【六大原则】

    开发一个系统并不是一件困难的事,但是为何维护好一个系统却是一件让人头疼不以的事?   在笔者的观念中这一切都源自于需求.   如果在软件开发完成之后,需求就不再改变,那大部分程序都不需要维护了.但是, ...

  5. 关于JavaScript原型对象那些事儿

    ①为什么要使用原型:为了实现继承. ②利用constructor属性可以让实例化对象轻松访问原型,实现实例化对象对原型对象的修改,但是原型对象是全局对象,一般不能随意修改原型对象的成员.该属性多用于调 ...

  6. python-组合模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 组合模式主要用来处理一类具有“容器特征”的对象——它们即充当对象又可以作为容器包 ...

  7. python-工厂方法模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 简单工厂模式的不足: 在简单工厂模式中,只提供了一个工厂类,该工厂类处于对产品类进行实例 ...

  8. js-ES6学习笔记-数值的扩展

    1.ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示. 2.如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法. 3.ES6在Number对象 ...

  9. ubuntu16.04安装matlab2016b

    一.matlab2016b版本下载 在ubuntu下安装matlab2016b,需要三个文件,分别是:Matlab+2016b+Linux64+Crack.rar .R2016b_glnxa64_dv ...

  10. MBTIles实现

    MBTIles实现 3.1 Compliant(符合) python: raster2mb (write) python: mbutil (read/write) python: landez (wr ...