[luogu P3195] [HNOI2008]玩具装箱TOY
[luogu P3195] [HNOI2008]玩具装箱TOY
题目描述
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过L。但他希望费用最小.
输入输出格式
输入格式:
第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7
输出格式:
输出最小费用
输入输出样例
输入样例#1:
5 4
3
4
2
1
4
输出样例#1:
1
开启斜率优化DP的学习。(可能因为状态原因,学的比较慢)
不太会讲理论,就对这道题讲一讲吧。
首先,我们可以列出一个n^2的转移方程:
f[i]=min(f[j]+(i-j-1+(s[i]-s[j])-L)^2)(j<i)。
将这个式子变化一下:
f[i]=min(f[j]+((i+s[i]-L-1)-(j+s[j]))^2)
设a[i]=i+s[i]-L-1,b[i]=i+s[i]。(当然也可以用一个数组,这里为了方便分辨)
则f[i]=min(f[j]+(a[i]-b[j])^2)=min(f[j]+a[i]^2-2a[i]b[j]+b[j]^2)。
即f[i]=?f[j]+a[i]^2-2a[i]b[j]+b[j]^2。
假装这是成立的,则设y=f[j]+b[j]^2,k=2a[i],x=b[j],b=f[i]-a[i]^2,
得到y=kx+b。
显然,我们需要让f[i]尽可能的小,就需要使得f[i]=b+a[i]^2尽可能小,也就是使b尽可能的小。
由于b=y-kx,其中k是确定的,y和x对于每一个j<i都是确定的,我们就可以将(x,y)表示在二维平面上。
现在,假如我们固定住x坐标,则y坐标要尽可能的小。
如果固定y坐标,则要尽可能增大x=b[j],根据前面的定义,b[]是单调递增的。但是由于y也是单调递增的,所以问题变得复杂了些。
那怎么办?这就涉及到了问题的本质。
对于一类转移方程:
f[i]=min{a[i]*b[j]+c[i]+d[j]}(a[i]和c[i]是常数,b[j]和d[j]与f[j]相关,j<i)
可以使用斜率优化。
稍微转换一下,考虑两个转移j和k,假如j比k更优,有a[i]*b[j]+c[i]+d[j]<a[i]*b[k]+c[i]+d[k]。
为方便考虑,设bj<bk,则得到-a[i]<(d[k]-d[j])/(b[k]-b[j]),这后面的就可以看成两点间直线的斜率。
那这就提示了我们,我们可以在两点间的斜率上做点功夫。
对于这题,沿用上面的式子,得到2a[i]<k(u,v)时,u比v更优。k(u,v)=(yv-yu)/(xv-xu)
这样,我们相当于要维护一个斜率直升不降的单调队列,每次询问时找出满足k(head,head+1)>2a[i]的head,然后,将更新后的f[i]插入到单调队列的队尾。
这样,我们就能将时间复杂度降到O(N)了。(个人觉得有点凌乱,如果读者觉得有上面地方表达不妥或有误,望指出)
code:
%:pragma GCC optimize()
#include<bits/stdc++.h>
#define sqr(x) ((x)*(x))
#define LL long long
using namespace std;
;
const double inf=1e18;
int n,L,l,r; LL f[N],c[N],a[N],b[N];
struct point {
LL x,y;
point() {}
point(LL _x,LL _y):x(_x),y(_y) {}
}st[N];
inline int read() {
; char ch=getchar();
') ch=getchar();
+ch-',ch=getchar();
return x;
}
double slope(point u,point v) {
return u.x==v.x?(u.y<v.y?inf:-inf):1.0*(v.y-u.y)/(v.x-u.x);
}
LL get(LL k) {
])<1.0*k) l++;
return st[l].y-k*st[l].x;
}
void insert(point cur) {
],st[r])>slope(st[r-],cur)) r--;
st[++r]=cur;
}
int main() {
n=read(),L=read(),c[]=;
; i<=n; i++) c[i]=c[i-]+read();
; i<=n; i++) a[i]=i+c[i]-L-;
; i<=n; i++) b[i]=i+c[i];
memset(f,,sizeof f);
l=,r=,st[++r]=point(,);
,j; i<=n; i++) {
f[i]=*a[i])+sqr(a[i]);
insert(point(b[i],f[i]+b[i]*b[i]));
}
printf("%lld\n",f[n]);
;
}
[luogu P3195] [HNOI2008]玩具装箱TOY的更多相关文章
- P3195 [HNOI2008]玩具装箱TOY(斜率优化dp)
P3195 [HNOI2008]玩具装箱TOY 设前缀和为$s[i]$ 那么显然可以得出方程 $f[i]=f[j]+(s[i]-s[j]+i-j-L-1)^{2}$ 换下顺序 $f[i]=f[j]+( ...
- P3195 [HNOI2008]玩具装箱TOY 斜率优化dp
传送门:https://www.luogu.org/problem/P3195 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任 ...
- 洛谷P3195 [HNOI2008]玩具装箱TOY——斜率优化DP
题目:https://www.luogu.org/problemnew/show/P3195 第一次用斜率优化...其实还是有点云里雾里的: 网上的题解都很详细,我的理解就是通过把式子变形,假定一个最 ...
- 洛谷P3195 [HNOI2008]玩具装箱TOY(单调队列优化DP)
题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...
- P3195 [HNOI2008]玩具装箱TOY
列出DP方程式:设f[i]表示分组完前i件物品的最小花费,为方便计算,设sum[i]表示是前i件物品的长度和. f[i]=min(f[j]+(sum[i]-sum[j]+i-j-L-1)^2) [0& ...
- [洛谷P3195][HNOI2008]玩具装箱TOY
题目大意:有n个物体,大小为$c_i$.把第i个到第j个放到一起,容器的长度为$x=j-i+\sum\limits_{k-i}^{j} c_k$,若长度为x,费用为$(x-L)^2$.费用最小. 题解 ...
- 洛谷P3195 [HNOI2008]玩具装箱TOY 斜率优化
Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn = 100000 ...
- 洛谷 P3195 [HNOI2008]玩具装箱TOY
题意简述 有n个物体,第i个长度为ci 将n个物体分为若干组,每组必须连续 如果把i到j的物品分到一组,则该组长度为 \( j - i + \sum\limits_{k = i}^{j}ck \) 求 ...
- Luogu P3195 [HNOI2008]玩具装箱
题目 预处理\(C\)的前缀和\(sum\).设前\(i\)个物品的最小答案为\(f\). \(f_i=\max\limits_{j\in[1,i)}(f_j+(sum_i-sum_j-L)^2)\) ...
随机推荐
- 【译】第45节---EF6-索引属性
原文:http://www.entityframeworktutorial.net/entityframework6/index-attribute-in-code-first.aspx Entity ...
- 爬虫系列之BeautifulSoup
BeautifulSoup是处理爬虫的一个强大工具,在HTML页面中,是由各种标签构成的,BeautifulSoup的功能就是从标签下手的,它是解析.遍历.维护“标签树”的功能库. Beautiful ...
- toggle 1.9 以后就被删除了
toggle 1.9 以后就被删除了, 1.8.x 以前可用. $(function(){ $(".p_title").toggle( function(){ $(this).n ...
- async函数对比Generator函数
首先定义一个读取文件的异步函数 var readFile = function(fileName){ return new Promise((resolve,reject)=>{ fs.read ...
- IPC 之 AIDL 的使用
一.AIDL 知识储备 1. AIDL 文件支持的数据类型: 基本数据类型 (int , long , char , boolean ,double 等): String 和 CharSequence ...
- strip函数
f=open('a.txt',)for l in f.readlines(): print(l.strip()) # 默认清除字符串l的首尾位的\n或空格,如果是l.strip("a&qu ...
- Codeforces 1076 E - Vasya and a Tree
E - Vasya and a Tree 思路: dfs动态维护关于深度树状数组 返回时将当前节点的所有操作删除就能保证每次访问这个节点时只进行过根节点到当前节点这条路径上的操作 代码: #pragm ...
- Unity --- 纹理为什么要设置为2的N次方
1.图片的纹理像素在Unity3D中需要遵循2的N次方,由图形学决定的,只识别2的N次方. 非2的N次方的图片会转化为2的N次方图片(500 x 500 → 512 x 512),是因为转化过程比 ...
- 第 8 章 容器网络 - 057 - macvlan 网络隔离和连通
macvlan 网络隔离和连通 验证 macvlan 之间的连通性. bbox1 能 ping 通 bbox3,bbox2 能 ping 通 bbox4. 即:同一 macvlan 网络能通信. bb ...
- layui: 子iframe关闭/传值/刷新父页面
https://www.cnblogs.com/jiqing9006/p/5135697.html layer iframe层的使用,传参 父层 <div class="col-x ...