【GDOI2014模拟】服务器 题解+代码

55 篇文章 0 订阅

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
最终结果可能较大,请注意选择适当的数据类型进行计算。

Solution

其实吧,这道题并不难。
我是从右往左做
F[i]表示到i这个点并且i直接复制的最小总费用,那么i左边没做到的就直接全部当做从i间接复制过去的。
那么 O(n2) 的DP就出来了
F[i]=min(f[j]+c[i]+(ji)(ji1)/2) 这里的最后一项就是i到j之间的点间接复制的费用和。
60分轻松拿到。
显然斜率优化就100分了。
点j比点k转移到点i优的条件就是上面的min里面的东西小。先把c[i]忽略掉。
f[j]+(ji)(ji1)/2<f[k]+(ki)(ki1)/2
化简得
(f[j]f[k]+(j2k2j+k)/2)/(jk)<i 我设为g(j,k)
单调队列第第一项为q1,第二项为q2…..
那么在单调队列中必须满足
i>g(q1,q2)>g(q2,q3)>g(q3,q4)
那么只要维护这个就行了,每个i做完后将i入队,注意要保证单调性
开longlong

code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 1100000
#define ll long long
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define fd(i,a,b) for(ll i=a;i>=b;i--)
using namespace std;
ll c[N],f[N],ans,d[N],n;
double ak(ll j,ll k)
{
    return (f[j]-f[k]+(j*j-k*k-j+k)*1.0/2)*1.0/(j-k)*1.0;
}
int main()
{
    scanf("%lld",&n);
    fo(i,1,n) scanf("%lld",&c[i]);
    f[n]=c[n];ans=f[n]+(n*(n-1)/2);int q=0,w=0;d[w]=n;
    fd(i,n-1,1)
    {
        if (w>q) {for(;ak(d[q],d[q+1])>=i;q++) if(w==q) break;}
        ll j=d[q];
        f[i]=f[j]+((j-i)*(j-i-1)/2)+c[i];
        ans=min(ans,f[i]+(i*(i-1)/2));
        if (w>q){for(;ak(d[w-1],d[w])<ak(d[w],i);w--) if(w==q) break;}  
        d[++w]=i;
    }
    printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值