【JZOJ 3432】【OnlineJudge 1061】小M的服务器(含斜率优化解释)

来源:互联网 发布:java开源聊天机器人 编辑:程序博客网 时间:2024/06/05 22:54

Description

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

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

Solution

首先这题的60分方法很简单,只用fi表示第i个必选的最小代价;
我们来考虑考虑用斜率优化,
设当前到i,状态j比k要优(j在前),则有:

fj+(ji)(ji1)2<fk+(ki)(ki1)2

移项:
fjfk+j2k2j+k2jk<i

用g(j,k)来表示这个东西,搞一波斜率优化DP即可,
复杂度:O(2n);


这里顺便讲一下斜率优化:

斜率优化

斜率优化的g函数是一定满足一个单调性的,前面的一定优于后面的,以本题为例:
设队列中的元素依次为j1j2,j3,...
有:(这个显然)

i>g(j1,j2)i>g(j2,j3)i>g(j3,j4)...

也有:
i>g(j1,j2)>g(j2,j3)>g(j3,j4)>...

解释如下:假设相邻的3个元素:j1,j2,j3
要想保证以上的式子,就必须当g(j1,j2)<g(j2,j3)时,删除j2
因为:假设j2最优,则:
g(j1,j2)>i

g(j2,j3)<i

g(j2,j3)<i<g(j1,j2)

与上面的假设冲突,所以假设不成立,
所以当g(j1,j2)<g(j2,j3)时,删除j2
所以整个式子满足:i>g(j1,j2)>g(j2,j3)>g(j3,j4)>...

Code

#include<cstdio>#include<cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(LL i=a;i>=b;i--)using namespace std;typedef long long LL;const int N=1000500;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n;int a[N],S,T;LL f[N],d[N];double G(LL i,LL j){return(1.0*(f[i]-f[j]+(i*i-j*j-i+j)/2)/(i-j));} int main(){    read(n);    fo(i,1,n) read(a[i]);    f[n]=a[n];d[S=T=1]=n;    fod(i,n-1,0)    {        while(T>S&&G(d[S],d[S+1])>i)S++;        f[i]=(d[S]-i)*(d[S]-i-1)/2+f[d[S]]+a[i];        while(T>S&&G(d[T-1],d[T])<G(d[T],i))T--;        d[++T]=i;    }    printf("%lld\n",f[0]);    return 0;}
2 0
原创粉丝点击