洛谷 P4072 [SDOI2016]征途 斜率优化DP

题目描述

\(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途。

从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相邻两段路的分界点设有休息站。

\(Pine\)计划用\(m\)天到达\(T\)地。除第\(m\)天外,每一天晚上\(Pine\)都必须在休息站过夜。所以,一段路必须在同一天中走完。

\(Pine\)希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。

帮助\(Pine\)求出最小方差是多少。

设方差是\(v\),可以证明,\(v\times m^2\)是一个整数。为了避免精度误差,输出结果时输出\(v\times m^2\)。

输入格式

第一行两个数 \(n\)、\(m\)。

第二行 \(n\) 个数,表示 \(n\) 段路的长度

输出格式

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

输入输出样例

输入 #1

5 2

1 2 5 8 6

输出 #1

36

说明/提示

对于 \(30\%\) 的数据,\(1 \le n \le 10\)

对于 \(60\%\) 的数据,\(1 \le n \le 100\)

对于 \(100\%\) 的数据,\(1 \le n \le 3000\)

保证从 \(S\) 到 \(T\) 的总路程不超过 \(30000\) 。

分析

\[s^2 \times m^2=\frac{(v_1-\overline{v})^2+(v_2-\overline{v})^2+...+(v_m-\overline{v})^2}m \times m^2
\]

\[s^2 \times m^2=((v_1-\overline{v})^2+(v_2-\overline{v})^2+...+(v_m-\overline{v})^2) \times m
\]

\[s^2 \times m^2=m\times \sum_{i=1}^mv_i^2+m^2 \times \overline {v}^2-2\times m \times \overline {v} \times sum[n]
\]

又因为$$\overline{v}=\frac{sum[n]}{m}$$

所以

\[s^2\times m^2=m\times \sum_{i=1}^mv_i^2-sum[n]\times sum[n]
\]

后面的值是固定的,所以我们只需要让前面的值最小化即可

我们设\(f[i][j]\)为前\(i\)天分成\(j\)段所得到的最小值

那么就有

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

展开就有

\[f[i][k]=f[j][k-1]+sum[i]^2+sum[j]^2-2\times sum[i] \times sum[j]
\]

移项得

\[f[j][k-1]+sum[j]^2=2\times sum[i] \times sum[j]+f[i][k]-sum[i]^2
\]

可以用斜率优化

我们把\(f[j][k-1]+sum[j]^2\)看成\(y\)

把\(2 \times sum[i]\)看成\(k\)

把\(sum[j]\)看成\(x\)

把\(f[i][k]-sum[i]^2\)看成\(b\)

这样,对于每一个\(i\)来说,直线的\(k\)是确定的

我们要使\(f[i][k]\)最小,也就是要使\(b\)最小

我们可以把所有的\(j\)想象成空间中的点

知道了斜率,知道了直线上的点,那么这条直线就确定了

那么我们考虑什么样的点使直线的\(b\)最大

直线\(l\)是我们要移动的直线,平面中的点是可以转移的\(j\)值

我们会发现当当前点和后一个点形成的直线的斜率恰好大于直线\(l\)的斜率是,由当前点转移决策是最优的

这就是代码里面的

while(head<tail && xl(q[head],q[head+1])<2*sum[j]) head++;
f[j]=g[q[head]]+sum[j]*sum[j]+sum[q[head]]*sum[q[head]]-2*sum[j]*sum[q[head]];

我们再去考虑什么样的点肯定不会对结果产生贡献

上面的图中\(2\)号节点是无论如何也不会更新其它节点的

因为\(1\)号节点或\(3\)号节点总会比它更优

这就是代码里的

 while(head<tail && xl(q[tail-1],q[tail])>=xl(q[tail],i)) tail--;

整个过程就相当于维护了一个下凸包

但是,如果斜率不是单调递增,我们就不能从前面清空队列直接转移,只能二分答案

比如上面这幅图如果我们一直从前清空队列的话那么就会把\(2\)号决策点弹出队列

但是如果之后遇到一个斜率比较小的直线\(m\)那么就不能转移到最优解

代码

#include<cstdio>
#include<cstring>
inline int read(){
int x=0,fh=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5;
int a[maxn],sum[maxn],n,m,f[maxn],g[maxn],q[maxn],head,tail;
double xl(int i,int j){
return (double)(g[i]+sum[i]*sum[i]-g[j]-sum[j]*sum[j])/(double)(sum[i]-sum[j]);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
sum[i]=sum[i-1]+a[i];
g[i]=sum[i]*sum[i];
}
for(int i=1;i<m;i++){
head=tail=1;
q[1]=i;
for(int j=i+1;j<=n;j++){
while(head<tail && xl(q[head],q[head+1])<2*sum[j]) head++;
f[j]=g[q[head]]+sum[j]*sum[j]+sum[q[head]]*sum[q[head]]-2*sum[j]*sum[q[head]];
while(head<tail && xl(q[tail],q[tail-1])>xl(q[tail-1],j)) tail--;
q[++tail]=j;
}
for(int j=1;j<=n;j++) g[j]=f[j];
}
printf("%d\n",f[n]*m-sum[n]*sum[n]);
return 0;
}

洛谷 P4072 [SDOI2016]征途 斜率优化DP的更多相关文章

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

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

  2. bzoj4518[Sdoi2016]征途 斜率优化dp

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

  3. 洛谷P4072 [SDOI2016]征途(带权二分,斜率优化)

    洛谷题目传送门 一开始肯定要把题目要求的式子给写出来 我们知道方差的公式\(s^2=\frac{\sum\limits_{i=1}^{m}(x_i-\overline x)^2}{m}\) 题目要乘\ ...

  4. 洛谷P4072 [SDOI2016]征途(斜率优化)

    传送门 推式子(快哭了……)$$s^2*m^2=\sum _{i=1}^m (x_i-\bar{x})^2$$ $$s^2*m^2=m*\sum _{i=1}^m x_i^2-2*sum_n\sum ...

  5. BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]

    4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...

  6. 【bzoj4518】[Sdoi2016]征途 斜率优化dp

    原文地址:http://www.cnblogs.com/GXZlegend/p/6812435.html 题目描述 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界 ...

  7. [SDOI2016]征途 —— 斜率优化DP

    时隔多年没有碰斜率优化了... 想当年被斜率优化虐的死去活来,现在看看...也就那样吧. Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计 ...

  8. [洛谷P4072] SDOI2016 征途

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

  9. [SDOI2015][bzoj4518] 征途 [斜率优化dp]

    题面 传送门 思路 把$vm^2$展开化一下式子,可以得到这样的等价公式: $vm^2=m\sum_{i=1}^m a_i^2-\sum_{i=1}^m a_i$ 那么我们要最小化的就是$\sum_{ ...

随机推荐

  1. dom4j基本操作

    DOM4J与利用DOM.SAX.JAXP机制来解析xml相比,DOM4J 表现更优秀,具有性能优异.功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml. ...

  2. Dubbo系列之 (二)Registry注册中心-注册(1)

    引导 dubbo的服务的注册与发现,需要通过第三方注册中心来协助完成,目前dubbo支持的注册中心包括 zookeeper,consul,etcd3,eureka,nacas,redis,sofa.这 ...

  3. Cenos系统防火墙开放指定端口

    1.查看已经开放的端口 firewall-cmd --list-ports 2.开启指定端口 firewall-cmd --zone=public --add-port=2181/tcp --perm ...

  4. 关于vector的自我补充

    insert()函数,选择性插入. insert(v.begin()+i,x)意思就是把x插入vector数组v的第i位置上(也是迭代器的位置上),其后面的数字都会自动后移.注意i是从0开始的! er ...

  5. eric4 打包文件

    在.py 工程 所在目录: 按住shift,鼠标右键,在此处打开cmd或shell,然后如下操作 1.打包成文件夹 pyinstaller lrs.py 2.打包成 单文件 pyinstaller - ...

  6. 《从缺陷中学习CC++》总结

    从缺陷中学习CC++总结 从本质上来说,这就是一个CC++的错题集.全书中包括63个问题引发的错误,即书名中的缺陷.共分为10章,每一张还有一个比较经典的小结,个人感觉这本书只需要仔细看一下每一章后面 ...

  7. linux线程控制-2(线程控制函数)

    记录肖堃老师讲解的linux线程 1. 创建线程 int pthread_create( (pthread_t *thread, pthread_attr_t *attr, void *(*start ...

  8. Jmeter 常用函数(13)- 详解 __machineIP

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回机器(电脑)IP 语法格式 ${_ ...

  9. 基于函数的I/O操作(头文件stdio.h)

    基于函数库的I/O是C语言标准库的功能,基于系统级I/O函数实现. 系统级I/O函数对文件的标识是文件描述符,C语言标准库中对文件的标识是指向FILE结构的指针.在头文件cstdio或stdio.h中 ...

  10. 计算机网络-应用层(1)Web应用与HTTP协议

    Web 页面(Web page,也叫文档)是由对象组成的. 对象:HTML文件.JPEG图片.视频文件.动态脚本等,通过一个URL地址寻址.每个URL地址由存放对象的服务器主机名和对象的路径名组成. ...