【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

时间:2023-03-09 07:13:09
【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【题目大意】

P教授有编号为1...N的N件玩具,第i件玩具长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。如果将第i件玩具到第j个玩具放到一 个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关, 如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。求最小费用。

【思路】

懒得说了,把WC宋新波老师的课件搬运一下。

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

宋新波老师讲的很好,WC的时候第一次听斜率优化听他讲完秒懂了,时隔几个月再来消化一下。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=+;
int n,l;
int c[MAXN];
LL s[MAXN],g[MAXN],x[MAXN],y[MAXN],f[MAXN]; LL square(LL x)
{
return x*x;
} double slop(int i,int j)
{
return ((y[j]-y[i])/(x[j]-x[i]));
} void dp()
{
memset(f,,sizeof(f));
int head=,tail=;
int q[MAXN];
q[head]=;
for (int i=;i<=n;i++)
{
y[i]=f[i-]+square(x[i]);
while (head+<tail && slop(q[tail-],q[tail-])>slop(q[tail-],i)) tail--;
q[tail++]=i;
while (head+<tail && slop(q[head],q[head+])<2.0*g[i]) head++;
f[i]=f[q[head]-]+square(g[i]-x[q[head]]);
}
} void init()
{
scanf("%d%d",&n,&l);
memset(s,,sizeof(s));
for (int i=;i<=n;i++)
{
scanf("%d",&c[i]);
s[i]=s[i-]+c[i];
g[i]=s[i]+i-l;
x[i]=s[i-]+i;
}
} void printans()
{
printf("%lld",f[n]);
} int main()
{
init();
dp();
printans();
return ;
}