洛谷P3195||bzoj1010 [HNOI2008]玩具装箱TOY
设s数组为C的前缀和
首先$ans_i=min_{j<i}\{ans_j+(i-j-1+s_i-s_j-L)^2\}$
(斜率优化dp)参考(复读)https://www.cnblogs.com/orzzz/p/7885971.html
设j不比k劣,则$ans_j+(i-j-1+s_i-s_j-L)^2 <= ans_k+(i-k-1+s_i-s_k-L)^2$
化简,与i相关的放到一边,(由于要除法,设$k+s_k-j-s_j>0$)
得$2(i+s_i)<=\frac{x_k-x_j+(k+s_k)^2-(j+s_j)^2+2(k+s_k)(L+1)-2(j+s_j)(L+1)}{k+s_k-j-s_j}$
设$f(k)=x_k+(k+s_k)^2+2(k+s_k)(L+1)$,$g(k)=k+s_k$,则$2(i+s_i)<=\frac{f(k)-f(j)}{g(k)-g(j)}$
也就是说,当$g(k)>g(j)$时,当且仅当满足这个条件时,j不比k劣
对于每个j,都表示为二维平面上一个点$(g(j),f(j))$
如果有
这样三个点i,j,k(图中横坐标分别改成g(i),g(j),g(k)),
那么$\frac{f(i)-f(j)}{g(i)-g(j)}<\frac{f(j)-f(k)}{g(j)-g(k)}$
可以发现,不管$2(i+s_i)$会插入到与这两者有关的什么位置(比两者都小,夹在中间,比两者都大),j都不可能是最优解
因此,只有下凸壳上面的点才可能是最优解,可以在算出i的答案并加入i的同时维护一下下凸壳(此处$g(i)=i+s_i$是单调的,直接栈维护即可)
怎么样在下凸壳找到这个最优解呢?
考虑
这样三个点i,j,k(图中横坐标分别改成g(i),g(j),g(k)),
那么$\frac{f(i)-f(j)}{g(i)-g(j)}>\frac{f(j)-f(k)}{g(j)-g(k)}$
可以发现,如果$2(i+s_i)$比两者都大,那么i最优;如果夹在中间,则j最优;如果比两者都小,则k最优
把3个点扩展到很多个点,可以发现如果搞出一个线段集合,表示下凸壳相邻两点间连线的集合,在这个集合中取出一条斜率>$2(i+s_i)$并且最小的线段,这条线段靠前(靠左)的那个点就是最优解(意会一下)(下凸壳边界点可能要特判)
由于此处$2(i+s_i)$是单调的,可以用一个指针直接维护这个最优解的位置
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
struct P
{
ll x,y,n;
};
P operator-(const P &a,const P &b)
{
return (P){a.x-b.x,a.y-b.y,};
}
ll cross(const P &a,const P &b)
{
return a.x*b.y-b.x*a.y;
}
inline ll sqr(ll x){return x*x;}
P tmp[];int l,r;
int n;ll L;
ll s[],ans[];
int main()
{
int i;ll t1;P tn;
scanf("%d%lld",&n,&L);
for(i=;i<=n;++i)
{
scanf("%lld",s+i);
s[i]+=s[i-];
}
l=;r=;
tmp[++r]=(P){,,};
for(i=;i<=n;++i)
{
t1=*(i+s[i]);
while(l<r && tmp[l+].y-tmp[l].y <= t1*(tmp[l+].x-tmp[l].x)) ++l;
if(l>r) l=r;
ans[i]=ans[tmp[l].n]+sqr(i-tmp[l].n-+s[i]-s[tmp[l].n]-L);
tn=(P){i+s[i],ans[i]+(i+s[i])*(i+s[i]+*L+),i};
while(r>= && cross(tn-tmp[r-],tmp[r]-tmp[r-])>=) --r;
tmp[++r]=tn;
}
printf("%lld\n",ans[n]);
return ;
}
为什么是凸包呢?好像还有一种解释方法
化简一下$ans_j+(i-j-1+s_i-s_j-L)^2$=$(i+s_i)^2-2(i+s_i)(j+s_j+L+1)+(j+s_j+L+1)^2+x_j$
其中$(i+s_i)^2$只与i有关,先提出去,
剩下$-2(i+s_i)(j+s_j+L+1)+(j+s_j+L+1)^2+x_j$
设其为z,现在要求z的最小值
发现这个过程类似线性规划,等式为$z=-2(i+s_i)(j+s_j+L+1)+(j+s_j+L+1)^2+x_j$
即$(j+s_j+L+1)^2+x_j=2(i+s_i)(j+s_j+L+1)+z$
设$x=j+s_j+L+1$,$y=(j+s_j+L+1)^2+x_j$,$a=2(i+s_i)$,则$y=ax+z$
对于每个j<i,可以看做平面上一个点(x,y),得到点集S
现在有直线$y=ax+z$,a是定值,z不确定,要使得它经过S中一个点,且截距z最小,就拿这条直线从右往左移,碰到第一个点时停下来
显然,只有点集的下凸壳上的点有可能被靠到(也有可能靠到下凸壳的一条边上,这时边的两个端点都是最优解)
下凸壳的性质是:形成它的各条线段的斜率递增
因此,要找到这条直线会靠到什么地方,维护下凸壳,在上面按斜率二分一下就行(这题有特殊性质,也可以用一个指针维护)
话说推出来的式子跟上面不一样,但是仍然可以A?
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
struct P
{
ll x,y,n;
};
P operator-(const P &a,const P &b)
{
return (P){a.x-b.x,a.y-b.y,};
}
ll cross(const P &a,const P &b)
{
return a.x*b.y-b.x*a.y;
}
inline ll sqr(ll x){return x*x;}
P tmp[];int l,r;
int n;ll L;
ll s[],ans[];
int main()
{
int i;ll t1;P tn;
scanf("%d%lld",&n,&L);
for(i=;i<=n;++i)
{
scanf("%lld",s+i);
s[i]+=s[i-];
}
l=;r=;
tmp[++r]=(P){L+,sqr(L+),};
for(i=;i<=n;++i)
{
t1=*(i+s[i]);
while(l<r && tmp[l+].y-tmp[l].y <= t1*(tmp[l+].x-tmp[l].x)) ++l;
if(l>r) l=r;
ans[i]=ans[tmp[l].n]+sqr(i-tmp[l].n-+s[i]-s[tmp[l].n]-L);
tn=(P){i+s[i]+L+,ans[i]+sqr(i+s[i]+L+),i};
while(r>= && cross(tn-tmp[r-],tmp[r]-tmp[r-])>=) --r;
tmp[++r]=tn;
}
printf("%lld\n",ans[n]);
return ;
}
其他资料(未看,咕咕咕)
https://www.cnblogs.com/MashiroSky/p/6009685.html
https://blog.csdn.net/lxc779760807/article/details/51366552
https://codeforces.com/blog/entry/63823
https://www.cnblogs.com/flashhu/p/9480669.html
洛谷P3195||bzoj1010 [HNOI2008]玩具装箱TOY的更多相关文章
- bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 11893 Solved: 5061[Submit][S ...
- bzoj1010: [HNOI2008]玩具装箱toy(DP+斜率优化)
1010: [HNOI2008]玩具装箱toy 题目:传送门 题解: 很明显的一题动态规划... f[i]表示1~i的最小花费 那么方程也是显而易见的:f[i]=min(f[j]+(sum[i]-su ...
- [BZOJ1010] [HNOI2008] 玩具装箱toy (斜率优化)
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- [bzoj1010](HNOI2008)玩具装箱toy(动态规划+斜率优化+单调队列)
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有 的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1.. ...
- [BZOJ1010][HNOI2008]玩具装箱toy 解题报告
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- BZOJ1010 [HNOI2008]玩具装箱toy
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- BZOJ1010 [HNOI2008]玩具装箱toy 动态规划 斜率优化
原文链接http://www.cnblogs.com/zhouzhendong/p/8687797.html 题目传送门 - BZOJ1010 题意 一个数列$C$,然后把这个数列划分成若干段. 对于 ...
- 2018.09.05 bzoj1010: [HNOI2008]玩具装箱toy(斜率优化dp)
传送门 一道经典的斜率优化dp. 推式子ing... 令f[i]表示装前i个玩具的最优代价. 然后用老套路. 我们只考虑把第j+1" role="presentation" ...
- 题解【bzoj1010 [HNOI2008]玩具装箱TOY】
斜率优化动态规划可以用来解决这道题.同时这也是一道经典的斜率优化基础题. 分析:明显是动态规划.令\(dp[i]\)为前\(i\)个装箱的最小花费. 转移方程如下: \[dp[i]=\min\limi ...
随机推荐
- 不重启linuxVMWare虚拟机添加虚拟磁盘
Vsphere Client找到要添加磁盘的虚机,如图所示 点击虚机右键,在出现的下列列表中选择“编辑设置”如图 在打开的虚拟机属性中,在”硬件对话框点击“添加"按钮,如图 在添 ...
- 随机数 while循环 do while循环 for循环
1.随机数 arc4random() 返回一个随机数 如果要随机[a,b]范围内的随机数 arc4random() % (b - a + 1) + a ; 2.break 跳出本次循 ...
- C#创建DataTable的语法
namespace EazyCMS.Web.admin { public partial class ceshi1 : System.Web.UI.Page { protected void Page ...
- IAR常用快捷键及技巧
1.复制和粘贴几行的部分代码 需求:有时候我们需要复制几行代码的后半部分,不需要复制前半部分.方法:按住Alt键,再用鼠标拖动就可以复制和粘贴后半部分 [END/2015-09-23] 2.复制一行 ...
- 三 volatile关键字
一:内存模型: 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问 ...
- 给JZ2440开发板重新分区
转自:http://mp.weixin.qq.com/s?__biz=MzAxNTAyOTczMw==&mid=2649328035&idx=1&sn=7d3935cc05d3 ...
- shell入门-awk-3
awk的内置变量 NR 表示行 NF 表示段 显示第十行 [root@wangshaojun ~]# awk -F ':' 'NR==10' 1.txtuucp:x:10:14:uucp:/var/s ...
- shell入门-特殊符号
特殊符号:* 说明:通配符,多个字符.所有后缀为”.txt“的文件列出来 [root@wangshaojun 111]# ls *.txt11.txt 1.txt 22.txt 2.txt 33.tx ...
- 使用struts2进行文件下载以及下载权限控制的例子
本测试有两个模块,一个是文件上上传,一个是文件下载,文件下载的时候会检查是否足有权限,如果没有,就会转发到登录页面,如果有权限,就会直接启动下载程序,给浏览器一个输出流. 下面直接上我的代码: 登录表 ...
- Java探索之旅(1)——概述与控制台输入
使用的课本: Java语言程序设计(基础篇)----西电 李娜(译) 原著: Introduction to Java Progrmming(Eighth Edition) -----Y.Daniel ...