8月P教授要去看奥运,但是他割舍不下自己的一大堆智力玩具。于是,他决定把所有玩具都运到北京去。P教授使用自己的物体维数压缩器ODZ(Object Dimension Zipper)来给玩具装箱。ODZ 可以将任意物品变成一维,再装到一种特殊的一维容器中。P教授有编号为1…N的N件玩具,第i件玩具经过ODZ处理后一维长度是Ci。为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时,如果一个一维容器中有多个玩具,那么相信两件玩具之间要加入1个单位长度的填充物。
形式地说,如果将第i到第j件玩具放在一个容器中,那容器的长度将为:
x=j-i+sigma(Ck) //i<=k<=j
制作容器的费用与容器长度有关。根据P教授的研究,如果容器长度为x,其制作费用为(x-L)^2,其中L是一个常量。P教授不关心容器的数目,他可以制造出任意长度的容器(甚至超过L),但他希望费用最小。
一年多没打斜率优化忘光了……复习一下
设 f [ i ] f[i] f[i]表示到第 i i i位的最小值,那么 O ( n 2 ) O(n^2) O(n2)的 D P DP DP方程很好写
f [ i ] = m i n ( f [ j ] + ( p r e [ i ] − p r e [ j ] + i − j − l − 1 ) 2 ) f[i]=min(f[j]+(pre[i]-pre[j]+i-j-l-1)^2) f[i]=min(f[j]+(pre[i]−pre[j]+i−j−l−1)2)
f [ k ] + ( g [ i ] − g [ k ] − c ) 2 ≤ f [ j ] + ( g [ i ] − g [ j ] − c ) 2 f[k]+(g[i]-g[k]-c)^2≤f[j]+(g[i]-g[j]-c)^2 f[k]+(g[i]−g[k]−c)2≤f[j]+(g[i]−g[j]−c)2
f [ k ] − 2 g [ i ] ( g [ k ] + c ) + ( g [ k ] + c ) 2 ≤ f [ j ] − 2 g [ i ] ( g [ j ] + c ) + ( g [ j ] + c ) 2 f[k]-2g[i](g[k]+c)+(g[k]+c)^2≤f[j]-2g[i](g[j]+c)+(g[j]+c)^2 f[k]−2g[i](g[k]+c)+(g[k]+c)2≤f[j]−2g[i](g[j]+c)+(g[j]+c)2
f [ k ] − f [ j ] ≤ 2 g [ i ] ( g [ k ] + c ) − ( g [ k ] + c ) 2 − 2 g [ i ] ( g [ j ] + c ) + ( g [ j ] + c ) 2 f[k]-f[j]≤2g[i](g[k]+c)-(g[k]+c)^2-2g[i](g[j]+c)+(g[j]+c)^2 f[k]−f[j]≤2g[i](g[k]+c)−(g[k]+c)2−2g[i](g[j]+c)+(g[j]+c)2
f [ k ] − f [ j ] + ( g [ k ] + c ) 2 − ( g [ j ] + c ) 2 ≤ 2 g [ i ] ( g [ k ] − g [ j ] ) f[k]-f[j]+(g[k]+c)^2-(g[j]+c)^2≤2g[i](g[k]-g[j]) f[k]−f[j]+(g[k]+c)2−(g[j]+c)2≤2g[i](g[k]−g[j])
f [ k ] − f [ j ] + ( g [ k ] + c ) 2 − ( g [ j ] + c ) 2 2 ( g [ k ] − g [ j ] ) ≤ g [ i ] { {f[k]-f[j]+(g[k]+c)^2-(g[j]+c)^2}\over{2(g[k]-g[j])}}≤g[i] 2(g[k]−g[j])f[k]−f[j]+(g[k]+c)2−(g[j]+c)2≤g[i]
然后按套路上单调队列斜率优化维护下凸壳就可以了
注意先删去较劣的队头后删去较劣的队尾
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include
#include
#include
#define MAXN 50005
#define mod 1000000007
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))
using namespace std;
ll a[MAXN],f[MAXN],g[MAXN],pre[MAXN],que[MAXN];
ll n,m;
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){
if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline ll sqr(ll x)
{
return x*x;
}
O3 inline double slope(ll x,ll y)
{
return 1.0*(f[x]+sqr(g[x]+m)-f[y]-sqr(g[y]+m))/(2.0*(g[x]-g[y]));
}
O3 int main()
{
//freopen("T1.in","r",stdin);
n=read(),m=read()+1;
fo(i,1,n)pre[i]=pre[i-1]+(a[i]=read()),g[i]=pre[i]+i;
ll head=1,tail=1;f[0]=que[1]=0;
fo(i,1,n)
{
while (head<tail && slope(que[head+1],que[head])<=g[i])++head;
f[i]=f[que[head]]+sqr(g[i]-g[que[head]]-m);
while (head<tail && slope(que[tail],que[tail-1])>=slope(i,que[tail]))--tail;
que[++tail]=i;
}
printf("%lld\n",f[n]);
return 0;
}