洛谷 P4072 [SDOI2016]征途 斜率优化DP
洛谷 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\) 。
分析
\]
\]
\]
又因为$$\overline{v}=\frac{sum[n]}{m}$$
所以
\]
后面的值是固定的,所以我们只需要让前面的值最小化即可
我们设\(f[i][j]\)为前\(i\)天分成\(j\)段所得到的最小值
那么就有
\]
展开就有
\]
移项得
\]
可以用斜率优化
我们把\(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的更多相关文章
- bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)
题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...
- bzoj4518[Sdoi2016]征途 斜率优化dp
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1657 Solved: 915[Submit][Status] ...
- 洛谷P4072 [SDOI2016]征途(带权二分,斜率优化)
洛谷题目传送门 一开始肯定要把题目要求的式子给写出来 我们知道方差的公式\(s^2=\frac{\sum\limits_{i=1}^{m}(x_i-\overline x)^2}{m}\) 题目要乘\ ...
- 洛谷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 ...
- BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]
4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...
- 【bzoj4518】[Sdoi2016]征途 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6812435.html 题目描述 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界 ...
- [SDOI2016]征途 —— 斜率优化DP
时隔多年没有碰斜率优化了... 想当年被斜率优化虐的死去活来,现在看看...也就那样吧. Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计 ...
- [洛谷P4072] SDOI2016 征途
问题描述 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路 ...
- [SDOI2015][bzoj4518] 征途 [斜率优化dp]
题面 传送门 思路 把$vm^2$展开化一下式子,可以得到这样的等价公式: $vm^2=m\sum_{i=1}^m a_i^2-\sum_{i=1}^m a_i$ 那么我们要最小化的就是$\sum_{ ...
随机推荐
- C# 委托 应用实例
用一句话解释委托:委托是一种可以把引用存储为函数的类型. 有些类似Spring框架对于接口的用法,向Action中注入Service对象.Action并不知道调用哪个服务层,只有容器通过配置文件 向A ...
- JS学习第二天
数组: var arr1=[2,5,6]; 定义时直接给数组元素赋值 var arr2=[]; 定义一个空数组 var arr3=new Array(); 定义一个空数组并通过索引来 ...
- 2020-07-26:如何用 socket 编程实现 ftp 协议?
福哥答案2020-07-26: 功能用户输入user username.pass password注册,注册后输入dir查看服务器文件列表,输入get filename path下载文件到指定路径. ...
- Flutter 容器 (2) - Padding
Padding: 内边距Widget,与CSS中的padding相似. import 'package:flutter/material.dart'; class AuthList extends S ...
- Golang | 既是接口又是类型,interface是什么神仙用法?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第12篇文章,我们来继续聊聊interface的使用. 在上一篇文章当中我们介绍了面向对象的一些基本概念,以及gol ...
- span和input布局时对不齐
如图 在span和input的css里各添加一行代码: vertical-align:top; (span和input在同一个盒子里)
- 面试不知如何回答这六大知识点,你还敢说熟悉MySQL?
文章目录 一.事务 1. 什么是事务 2. 事务的四大特性 3. 事务的并发问题 ① 事务并发问题什么时候发生? ② 事务的并发问题有哪些? ③ 如何避免事务的并发问题? 二.索引 1. 什么是索引 ...
- Python Unofficial Windows Binary
python一些安装包有时候在windows下无法 直接安装. 可以在一个非官方的Python Windows扩展库里面找到对应的打包好的whl,下载后直接安装. https://www.lfd.uc ...
- requests模块使用
一.python环境下安装requests Windows下使用win+r打开cmd命令提示符,输入pip install requests,回车. 二.requests模块导入 import req ...
- idea Maven项目 包下载不下来或者已经下载了就是飘红
0.先在settings.xml加上阿里的镜像在刷新试试 <mirror> <id>aliyunmaven</id> <mirrorOf>*</m ...