• bzoj3437 小P的牧场(斜率优化dp)


    3437: 小P的牧场

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2025  Solved: 1110
    [Submit][Status][Discuss]

    Description

    小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。
    1<=n<=1000000, 0 < a i ,bi < = 10000

    HINT

     

    Source


    每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场

    这时候逆推显然比正推好用

    于是我们设$s[i]$为$b[i]$的前缀和,$f[i]$为只在第$i$~$n$个牧场中设置控制站,且在牧场$i$设置控制站的最小代价

    $f[i]=f[j]-(j-i)*s[i]+a[i]$

    $f[j]=s[i]*j+f[i]+i*s[i]+a[i]$

    又化成了喜闻乐见的$y=k*x+b$

    $y=f[j]$

    $k=s[i]$

    $x=j$

    $b=f[i]+i*s[i]+a[i]$

    $k,x$均单调

    于是我们就可以快乐地单调队列维护凸包解决辣·

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define rint register int
    using namespace std;
    typedef long long ll;
    #define N 1000005
    ll a[N],b[N],s[N],f[N],ans;
    int n,L,R,h[N];
    inline ll X(int i){return i;}
    inline ll Y(int i){return f[i];}
    inline ll KK(ll xa,ll ya,ll xb,ll yb){return ya*xb-yb*xa;}
    int main(){
        //freopen("bzoj3437.in","r",stdin);
        scanf("%d",&n);
        for(rint i=1;i<=n;++i) scanf("%lld",&a[i]);
        for(rint i=1;i<=n;++i) scanf("%lld",&b[i]),s[i]=s[i-1]+b[i];
        for(rint i=n-1;i;--i) f[n]+=1ll*(n-i)*b[i];
        f[n]+=a[n]; ans=f[n]; h[L=R=1]=n;//先把f[n]算出来
        for(rint i=n-1;i;--i){
            while(L<R&&KK(X(h[L+1])-X(h[L]),Y(h[L+1])-Y(h[L]),
            1,s[i])<=0) ++L;
             
            f[i]=f[h[L]]-1ll*(h[L]-i)*s[i]+a[i];
            ans=min(ans,f[i]);
            
            while(L<R&&KK(X(h[R])-X(h[R-1]),Y(h[R])-Y(h[R-1]),
            X(h[R])-X(i),Y(h[R])-Y(i))>=0) --R;
            
            h[++R]=i;
        }printf("%lld",ans);
        return 0;
    }

    Description

    小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。
    1<=n<=1000000, 0 < a i ,bi < = 10000

    HINT

     

    Source

  • 相关阅读:
    Python开发环境Spyder介绍
    Python干货整理之数据结构篇
    通过Python爬虫按关键词抓取相关的新闻
    疫情后来场说走就走的旅行,Python制作一份可视化的旅行攻略
    详细介绍去一年在 PyPI 上下载次数最多的 Python 包
    Python错误与异常
    python爬虫爬取2020年中国大学排名
    微信史上最短的一行功能代码:拍一拍
    Python爬取某宝商品数据案例:100页的价格、购买人数等数据
    我的SAS菜鸟之路7
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10758986.html
Copyright © 2020-2023  润新知