1010: [HNOI2008]玩具装箱toy
思路:斜率优化
设
Fi
为前
i
个玩具的最优答案
递推式:
斜率优化的思想咯:若j比k优,则有
Fj+(i−j−1+sumi−sumj−L)2<Fk+(i−k−1+sumi−sumk−L)2
基本数学知识可以化成:
[Fk+(sumk+k+L+1)2]−[Fj+(sumj+j+L+1)2]>2∗(sumk+k−sumj−j)∗(sumi+i)
sumi 与 i <script id="MathJax-Element-270" type="math/tex">i</script>都是单调递增的,除过去用朴素的斜率优化就好
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=50010;
typedef long long ull;
int n,L;
ull c[MAXN];
ull sum[MAXN];
ull f[MAXN];
int stack[MAXN];
int l,r;
ull a(int i) { return sum[i]+i; }
ull x(int i) { return 2*a(i); }
ull y(int i) { return f[i]+(a(i)+L+1)*(a(i)+L+1); }
void init()
{
cin>>n>>L;
for (int i=1;i<=n;i++) {
scanf("%I64d",&c[i]);
sum[i]=sum[i-1]+c[i]; }
l=r=0;
for (int i=1;i<=n;i++) {
while (l<r && (y(stack[l+1])-y(stack[l]))<=a(i)*(x(stack[l+1])-x(stack[l])))
stack[l++]=0;
f[i]=f[stack[l]]+(i-stack[l]-1+sum[i]-sum[stack[l]]-L)*(i-stack[l]-1+sum[i]-sum[stack[l]]-L);
while (l<=r && (y(i)-y(stack[r-1]))*(x(i)-x(stack[r]))>(y(i)-y(stack[r]))*(x(i)-x(stack[r-1])))
stack[r--]=0;
stack[++r]=i; }
cout<<f[n]<<endl;
return ;
}
int main()
{
init();
return 0;
}