BZOJ 1010 [HNOI2008]玩具装箱toy 斜率优化DP
2015-10-10 20:58
309 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1010
题目大意:
有N个玩具,第i个玩具长度为Ci,将他们分为任意组,若将第i个玩具到第j个玩具分为一组,则该组的长度x=j−i+∑jk=iCk,所需要花费的费用为(x−L)2,L为固定值。
1≤N≤50000;1≤L,Ci≤107
题解:
如果设sum[i]=∑ik=1Ck很容易就能写出状态转移方程
f[i]=min{f[j]+(i−j−1+sum[i]−sum[j]−L)2}
这里我们不妨设sum[i]=∑ik=1Ck+i,L=L+1,使代码更加简洁
状态转移方程变为f[i]=min{f[j]+(sum[i]−sum[j]−L)2}
朴素时间复杂度O(n2)肯定是不行的,所以我们用斜率优化DP将其优化至O(n)
将状态转移方程加以变换得
f[j]+(sum[j]+L)2=sum[i]∗2∗(sum[j]+L)+f[i]−(sum[i])2
令:
y=f[j]+(sum[j]+L)2;
k=sum[i];
x=2∗(sum[j]+L);
b=f[i]−(sum[i])2;
则状态转移方程变为y=kx+b
当做状态i的决策时,可以确定斜率k将之前的状态j所对应的点(xj,yj)代入即可求出截距b,进而求出f[i]
这相当于用一条斜率确定的直线穿过符合条件的点,使截距最小
如图,易知我们所选取的点一定是下凸壳上的点
我们用一个单调队列来维护这个下凸壳,每次用队首的元素更新状态,使每次求得的f[i]最小,并插入新的元素。
代码:
题目大意:
有N个玩具,第i个玩具长度为Ci,将他们分为任意组,若将第i个玩具到第j个玩具分为一组,则该组的长度x=j−i+∑jk=iCk,所需要花费的费用为(x−L)2,L为固定值。
1≤N≤50000;1≤L,Ci≤107
题解:
如果设sum[i]=∑ik=1Ck很容易就能写出状态转移方程
f[i]=min{f[j]+(i−j−1+sum[i]−sum[j]−L)2}
这里我们不妨设sum[i]=∑ik=1Ck+i,L=L+1,使代码更加简洁
状态转移方程变为f[i]=min{f[j]+(sum[i]−sum[j]−L)2}
朴素时间复杂度O(n2)肯定是不行的,所以我们用斜率优化DP将其优化至O(n)
将状态转移方程加以变换得
f[j]+(sum[j]+L)2=sum[i]∗2∗(sum[j]+L)+f[i]−(sum[i])2
令:
y=f[j]+(sum[j]+L)2;
k=sum[i];
x=2∗(sum[j]+L);
b=f[i]−(sum[i])2;
则状态转移方程变为y=kx+b
当做状态i的决策时,可以确定斜率k将之前的状态j所对应的点(xj,yj)代入即可求出截距b,进而求出f[i]
这相当于用一条斜率确定的直线穿过符合条件的点,使截距最小
如图,易知我们所选取的点一定是下凸壳上的点
我们用一个单调队列来维护这个下凸壳,每次用队首的元素更新状态,使每次求得的f[i]最小,并插入新的元素。
代码:
#include<stdio.h> typedef long long ll; int n; ll l; ll c[50005]; ll sum[50005]; ll f[50005]; int q[50005]; int head; int tail; ll y(int i) { return f[i]+(sum[i]+l)*(sum[i]+l); } ll x(int i) { return 2ll*(sum[i]+l); } double getk(int a,int b) { return (double)(y(b)-y(a))/(x(b)-x(a)); } int main() { scanf("%d%lld",&n,&l); l++; for(int i=1;i<=n;i++) { scanf("%lld",&c[i]); sum[i]=sum[i-1]+c[i]+1; ll k=sum[i]; while(tail-head&&getk(q[head],q[head+1])<=k) { head++; } f[i]=y(q[head])-k*x(q[head])+sum[i]*sum[i]; while(tail-head&&getk(q[tail-1],i)<=getk(q[tail-1],q[tail])) { tail--; } q[++tail]=i; } printf("%lld\n",f ); return 0; }
相关文章推荐
- BZOJ3275 Number (最小割)
- [bzoj1003] [ZJOI2006]物流运输trans
- [bzoj1500][NOI2005]维修数列
- [bzoj1208] [HNOI2004]宠物收养所
- [bzoj1269][AHOI2006]文本编辑器editort
- [bzoj1503][NOI2004]郁闷的出纳员
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- [BZOJ2594][WC2006][LCT][MST]水管局长数据加强版
- [BZOJ2300][HAOI2011][动态凸包]防线修建
- [BZOJ1045][HAOI2008][贪心]糖果传递
- [BZOJ2539][CTSC2000][KM]丘比特的烦恼
- [BZOJ1004][HNOI2008][Burnside引理][DP]Cards
- [BZOJ1202][HNOI2005][并查集]狡猾的商人
- [BZOJ1179][APIO2009][Tarjan][拓扑排序][递推]Atm
- [BZOJ1095][ZJOI2007][线段树]Hide捉迷藏
- [BZOJ1089][SCOI2003][递推][高精度]严格n元树
- [BZOJ1096][ZJOI2007][DP][斜率优化]仓库建设
- [BZOJ1071][SCOI2007][堆]组队
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- [BZOJ1266][AHOI2006][最短路][最小割]上学路线