[HNOI2008]玩具装箱TOY
题面:
https://www.lydsy.com/JudgeOnline/problem.php?id=1010
一道dp题,需要斜率优化。
代码:
#include<cstdio> #include<algorithm> using namespace std; #define N 50050 #define ll long long int n; ll c[N],s[N],l,f[N]; const ll inf = 9999999999999ll; int q[N],h,t; ll x(int i) { return -s[i]-1ll*i; } ll y(int i) { return f[i]+x(i)*x(i); } ll z(int i) { return (-s[i]+l+1ll-(ll)i); } ll k(int i) { return 2*z(i); } ll b(int i) { return z(i)*z(i); } int main() { scanf("%d%lld",&n,&l); for(int i=1;i<=n;i++) { scanf("%lld",&c[i]); s[i] = s[i-1] + c[i]; f[i] = inf; } for(int i=1;i<=n;i++) { while(h<t&&(y(q[h+1])-y(q[h]))<=(x(q[h+1])-x(q[h]))*k(i))h++; f[i] = y(q[h])-k(i)*x(q[h])+b(i); while(h<t&&(y(i)-y(q[t]))*(x(q[t])-x(q[t-1]))>=(y(q[t])-y(q[t-1]))*(x(i)-x(q[t])))t--; q[++t] = i; } printf("%lld\n",f[n]); return 0; }
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为 1⋯N1\cdots N1⋯N 的 NNN 件玩具,第 iii 件玩具经过压缩后变成一维长度为 CiC_iCi .为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第 iii 件玩具到第 jjj 个玩具放到一个容器中,那么容器的长度将为 x=j−i+∑k=ijCkx=j-i+\sum\limits_{k=i}^{j}C_kx=j−i+k=i∑jCk 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 xxx ,其制作费用为 (X−L)2(X-L)^2(X−L)2 .其中 LLL 是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 LLL 。但他希望费用最小.