【GDOI2014模拟】JZOJ2020年8月14日提高组 服务器
题目
Time and Memory Limits
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
题解
题意
给出
n
n
n个点
每个点可以选择两种操作
一种是直接复制,费用为
a
i
a_i
ai
一种是间接复制,费用为
i
i
i后面第一个直接复制的
j
j
j的
j
−
i
j-i
j−i
n
n
n号点必须直接复制
问最小代价
分析
考虑
D
P
DP
DP
设
f
[
i
]
f[i]
f[i]表示
i
i
i点直接复制和间接复制的总和
那么转移
f
[
i
]
=
m
i
n
{
f
[
j
]
+
j
∗
(
j
−
i
)
−
(
j
−
i
)
(
j
+
i
−
1
)
2
}
f[i]=min\{f[j]+j*(j-i)-\dfrac{(j-i)(j+i-1)}{2}\}
f[i]=min{f[j]+j∗(j−i)−2(j−i)(j+i−1)}
转移
n
2
n^2
n2,过不了
思考优化
发现可以斜率优化
优化
f
[
j
]
−
f
[
k
]
+
j
2
−
k
2
+
k
−
j
2
j
−
k
<
i
(
j
>
k
)
\dfrac{f[j]-f[k]+\dfrac{j^2-k^2+k-j}{2}}{j-k}<i(j>k)
j−kf[j]−f[k]+2j2−k2+k−j<i(j>k)
单调队列维护
Code
#include<bits/stdc++.h>
using namespace std;
long long n,l,r,ans,f[1000005],q[1000005],a[1000005];
long long read()
{
long long res=0;char ch;
ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9')
{
res=(res<<1)+(res<<3)+(ch-'0');
ch=getchar();
}
return res;
}
long long get(long long l,long long r)
{
return r*(r-l)-(r+l-1)*(r-l)/2;
}
double slope(long long x,long long y)
{
return (f[x]-f[y]+(x*x-y*y+y-x)/2)*1.0/(x-y);
}
int main()
{
n=read();
for (long long i=1;i<=n;i++)
a[i]=read();
f[n]=a[n];
l=1;
r=1;
q[1]=n;
for (long long i=n-1;i;i--)
{
while (l<r&&slope(q[l],q[l+1])>=i) l++;
f[i]=a[i]+f[q[l]]+get(i+1,q[l]);
while (l<r&&slope(q[r-1],q[r])<slope(q[r],i)) r--;
q[++r]=i;
}
ans=99999999999999;
for (long long i=1;i<=n;i++)
ans=min(ans,f[i]+get(1,i));
printf("%lld\n",ans);
return 0;
}