[bzoj 1010][HNOI 2008]玩具裝箱
阿新 • • 發佈:2019-01-08
傳送門
Description
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。但他希望費用最小.
Solution
斜率優化的練習題。
\(F_i=\min ({f_j+(sum_i-sum_j+i-j-l-1)^2})\)
我們令 \(g_i=sum_i+l\)
若\(j<k\),且決策\(k\)優於決策\(j\)
\(\frac{((f_k+(g_k+l+1)^2)-(f_j+(g_j+l+1))^2 )}{ (g_k - g_j)}<=2*f_i\)
Code
#include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define MN 50005 int n,L; ll f[MN],g[MN]; ll sqr(ll x){return x*x;} int que[MN],l=1,r=0; double calc(int j,int k) { return (double)(f[j]+sqr(g[j]+L)-f[k]-sqr(g[k]+L))/(double)(g[j]-g[k]); } void insert(int x) { for(;r>l&&calc(que[r],que[r-1])>=calc(x,que[r]);r--); que[++r]=x; } int get(int x) { if(l>r) return 0; for(;r>l&&calc(que[l+1],que[l])<=(double)2*g[x];l++); return que[l]; } int main() { n=read();L=read()+1; register int i,j; for(i=1;i<=n;++i) g[i]=g[i-1]+read()+1; f[0]=que[++r]=0; for(i=1;i<=n;++i) { j=get(i); f[i]=f[j]+sqr(g[i]-g[j]-L); insert(i); } printf("%lld\n",f[n]); }
Blog來自PaperCloud,未經允許,請勿轉載,TKS!