3432. 【GDOI2014模拟】服务器

Description

我们需要将一个文件复制到n个服务器上,这些服务器的编号为S1, S2, …, Sn。

首先,我们可以选择一些服务器,直接把文件复制到它们中;将文件复制到服务器Si上,需要花费ci > 0的置放费用。对于没有直接被复制文件的服务器Si来说,它依次向后检查Si+1, Si+2, …直到找到一台服务器Sj:Sj中的文件是通过直接复制得到的,于是Si从Sj处间接复制得到该文件,这种复制方式的读取费用是j – i(注意j>i)。另外,Sn中的文件必须是通过直接复制得到的,因为它不可能间接的通过别的服务器进行复制。我们设计一种复制方案,即对每一台服务器确定它是通过直接还是间接的方式进行复制(Sn只能通过直接方式),最终使每一台服务器都得到文件,且总花费最小。

Input

输入文件的第一行有一个整数n,表示服务器的数目。输入文件的第二行有n个整数,顺数第i个表示ci:在Si上直接复制文件的费用。

Output

输出文件中只包含一个整数,即最少需要花费的费用。

Sample Input

10

2 3 1 5 4 5 6 3 1 2

Sample Output

18

Data Constraint

60%的数据中,1 <= n <= 1 000

100%的数据中,1 <= n <= 1 000 000

80%的数据中, 1 <= ci <= 50

100%的数据中,1 <= ci <= 1 000 000 000

最终结果可能较大,请注意选择适当的数据类型进行计算。

Hint

Solution

斜率优化。注意x*(x+1)/2的时候也要开long long!

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define I int
#define ll long long
#define N 1000005
using namespace std;
I n,l,r,a[N],q[N];
ll f[N];
char c;
void R(I &x){
	x=0;c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
}
ll slope(ll x,ll y){return f[x]-f[y]+x*(x+1)/2-y*(y+1)/2;}
I main(){
	freopen("server.in","r",stdin);
	freopen("server.out","w",stdout);
	R(n);
	for(I i=1;i<=n;i++) R(a[i]);
	l=r=1;
	for(ll i=1;i<=n;i++){
		while(l<r&&slope(q[l],q[l+1])>i*(q[l]-q[l+1])) l++;
		f[i]=f[q[l]]+a[i]+(i-q[l])*(i-q[l]-1)/2;
		while(l<r&&slope(q[r],i)*(q[r-1]-q[r])<slope(q[r-1],q[r])*(q[r]-i)) r--;
		q[++r]=i;
	}
	printf("%lld\n",f[n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/108014112