列表

详情


NC20067. [HNOI2008]玩具装箱TOY

描述

P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。
P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i ≤ K ≤ j 
制作容器的费用与容器的长度有关,根据教授研究, 如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容 器,甚至超过L。但他希望费用最小.

输入描述

第一行输入两个整数N,L.接下来N行输入Ci.
1 ≤ N ≤ 50000,1 ≤ L,Ci ≤ 10^7

输出描述

输出最小费用

示例1

输入:

5 4
3
4
2
1
4

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 23ms, 内存消耗: 1340K, 提交时间: 2023-05-18 11:17:34

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
const int M=1e5;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
int n,L;
int l,r,que[N+5];
double dp[N+5],sum[N+5];
double A(int x){
	return sum[x]+x;
}
double B(int x){
	return sum[x]+x+L+1;
}
double slope(int x,int y){
	double val=(dp[y]+B(y)*B(y))-(dp[x]+B(x)*B(x));
	return val/(B(y)-B(x));
}
int main(){
    ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>L;
	for(int i=1;i<=n;i++){
		double x;cin>>x;
		sum[i]=sum[i-1]+x;
	}
	
	l=r=1;
	for(int i=1;i<=n;i++){
		while(l<r && slope(que[l],que[l+1])<2*A(i))l++;
		dp[i]=dp[que[l]]+(A(i)-B(que[l]))*(A(i)-B(que[l]));
		while(l<r && slope(que[r-1],i)<slope(que[r-1],que[r]))r--;
		que[++r]=i;
	}
	cout<<(long long)dp[n];
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 11ms, 内存消耗: 1036K, 提交时间: 2020-10-20 12:24:51

#include<bits/stdc++.h>
#define k(i,j) 1.0*(y[j]-y[i])/(x[j]-x[i])
using namespace std;
const int nn=51020;
int n,l,c,t,tt;
long long f,s,w,x[nn],y[nn];
int main(){
	scanf("%d%d",&n,&l);
	for(int i=1;i<=n;i++){
		scanf("%d",&c),s+=c+1,w=s-l-1;
		if(t>=tt)t=tt;
		else while(t<tt&&k(t,t+1)<(w<<1))t++;
		f=y[t]-2*w*x[t]+w*w,x[tt+1]=s,y[tt+1]=f+s*s;
		for(;tt&&k(tt-1,tt)>k(tt-1,tt+1);tt--)
			swap(x[tt],x[tt+1]),swap(y[tt],y[tt+1]);
		tt++;
	}return printf("%lld",f),0;
}

上一题