P3195 [HNOI2008]玩具装箱

#include<bits/stdc++.h>
#define N 50000+10
#define ll long long
#define go(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
ll s[N],f[N],L;
int queuee[N];

inline double X(int x){return s[x];}
inline double Y(int y){return f[y]+(s[y]+L)*(s[y]+L);}
inline double rate(int a,int b){
    double dx=X(a)-X(b);
    if(!dx)return LONG_MAX;
    return (Y(a)-Y(b))/dx;



}


int main(){

int n;

scanf("%d%lld",&n,&L);
++L;
go(i,1,n){
scanf("%lld",&s[i]);
s[i]+=s[i-1];
}

int head=1,tail=1;
queuee[1]=0;


go(i,1,n){
s[i]+=i;
}

go(i,1,n){
while(head<tail&&rate(queuee[head],queuee[head+1])<=2*(double)s[i])
    ++head;

int j=queuee[head];
f[i]=f[j]+(s[i]-s[j]-L)*(s[i]-s[j]-L);

while(head<tail&&rate(queuee[tail-1],queuee[tail])>rate(queuee[tail],i) )
    --tail;
queuee[++tail]=i;

}

printf("%lld",f[n]);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值