裸的斜率优化
刚开始我还很脑残的就把那个基本的式子带进去推(斜率式)了。。。可是那个实在是太复杂了,由此说明,如果我们可以尝试通过一些方法将式子简化,再代入斜率优化来推。
比如本题:容器长度x=j-i+Sigma(Ck) ,他是说,每一个玩具之间都要加一个单位长度隔开,其实就当玩具长度加一,一个组合的长度就是总长度-1(因为间隔数是玩具数-1)所以间隔要少一个。
这叫,优化dp的式子把,如果很麻烦的式子应该就是需要优化一下
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int N=60005;
ll f[N],sum[N],L;
int n,q[N],head,tail;
ll getup(int j)
{
return f[j]+(sum[j]+1)*(sum[j]+1)+2*L*sum[j];
}
ll getup(int j,int k)
{
return getup(j)-getup(k);
}
ll getdown(int j,int k)
{
return sum[j]-sum[k];
}
ll getdp(int i,int j)
{
return f[j]+(sum[i]-sum[j]-1-L)*(sum[i]-sum[j]-1-L);
}
int main()
{
scanf("%d%lld",&n,&L);
for (int i=1;i<=n;i++) scanf("%lld",&sum[i]),sum[i]++;
for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
head=tail=1;
q[1]=0;
for (int i=1;i<=n;i++)
{
while (head<tail &&
getup(q[head+1],q[head])<2*sum[i]*getdown(q[head+1],q[head])
) head++;
f[i]=getdp(i,q[head]);
while (head<tail &&
getup(i,q[tail])*getdown(q[tail],q[tail-1])<
getup(q[tail],q[tail-1])*getdown(i,q[tail])
) tail--;
q[++tail]=i;
}
printf("%lld",f[n]);
return 0;
}