• bzoj3437 小P的牧场


    Description


     背景

        小P是个特么喜欢玩MC的孩纸。。。

     描述

        小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量,在第i个牧场建立控制站的花费是ai,每个牧场i的放养量是bi,理所当然,小P需要总花费最小,但是小P的智商有点不够用了,所以这个最小总花费就由你来算出啦。

    Input

        第一行一个整数 n 表示牧场数目

        第二行包括n个整数,第i个整数表示ai

        第三行包括n个整数,第i个整数表示bi

    Output

       只有一行,包括一个整数,表示最小花费

    Sample Input

    4
    2424
    3142

    Sample Output


    9

    样例解释

    选取牧场1,3,4建立控制站,最小费用为2+(2+1*1)+4=9。

    数据范围与约定


    对于100%的数据,1<=n<=1000000,0<ai,bi<=10000

    斜率优化的dp

    有点麻烦

    f[i]表示1~i中在i放控制站的最小代价

    那么f[i]=min(f[j]+a[i]+Σb[k]*(i-k)|j<k<=i)

    然后算Σ的式子的时候首先b[i]可以用前缀和优化一下

    首先原式

    =s[i-1]-s[j]

    +s[i-2]-s[j]

    +s[i-3]-s[j]

    ……

    +s[j+1]-s[j]

    所以再搞出s[]的前缀和t[]

    那么最后化简完f[i]=min(f[j]+a[i]+t[i-1]-t[j]-s[j]*(i-j-1));

    然后考虑转移i的状态的时候,有j,k两个决策

    当f[j]+a[i]+t[i-1]-t[j]-s[j]*(i-j-1)<f[k]+a[i]+t[i-1]-t[k]-s[k]*(i-k-1)时j比k优

    即f[j]-s[j]-(f[k]-s[k])+s[j]*(j+1)-s[k]*(k+1)<i*(s[j]-s[k])

    于是可以用斜率优化了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<ctime>
    #define LL long long
    #define inf 10000000000000000ll
    #define pa pair<int,int>
    #define pi 3.1415926535897932384626433832795028841971
    #define N 1000010
    using namespace std;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    LL s[N],t[N],f[N];
    int a[N],b[N];
    int q[N],head,tail=1;
    LL cala(int x,int y)
    {
    	return f[x]-f[y]-(t[x]-t[y])+(s[x]*(x+1)-s[y]*(y+1));
    }
    LL calb(int x,int y)
    {
    	return s[x]-s[y];
    }
    int n;
    int main()          //f[i]=min(f[j]+a[i]+t[i-1]-t[j]-s[j]*(i-j-1));
    {
    	freopen("pasture.in","r",stdin);
    	freopen("pasture.out","w",stdout);
    	n=read();
    	for (int i=1;i<=n;i++)f[i]=inf;
    	for (int i=1;i<=n;i++)a[i]=read();
    	for (int i=1;i<=n;i++)b[i]=read();
    	for (int i=1;i<=n;i++)
    	{
    		s[i]=s[i-1]+b[i];
    		t[i]=t[i-1]+s[i];
    	}
    	for (int i=1;i<=n;i++)
    	{
    		while (tail-head>1 && cala(q[head+1],q[head])<=i*calb(q[head+1],q[head]))head++;
    		int from=q[head];
    		f[i]=f[from]+a[i]+t[i-1]-t[from]-s[from]*(i-from-1);
    		q[tail++]=i;
    		for (int k=tail-2;k>head;k--)
    		{
    			int x=q[k+1],y=q[k],z=q[k-1];
    			if (cala(y,z)*calb(x,y)>=cala(x,y)*calb(y,z))q[k]=q[--tail];
    			else break;
    		}
    	}
    	printf("%lld
    ",f[n]);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    non-blocking I/O
    jetty netty
    Azkaban_Oozie_action
    权限过大 ssh协议通过pem文件登陆
    交易准实时预警 kafka topic 主题 异常交易主题 低延迟 event topic alert topic 内存 算法测试
    flink_action
    netty
    1970 ted codd
    Data dictionary
    mina
  • 原文地址:https://www.cnblogs.com/zhber/p/4130567.html
Copyright © 2020-2023  润新知