• 【bzoj1096】仓库建设——斜率优化dp


    题目链接

    我们用sum[i]表示前i个工厂的产品数之和,b[i]表示x[i]*p[i]的前缀和,因此第j+1~i个工厂的产品运到第i个工厂的代价就是

      (sum[i]-sum[j])*x[i]-(b[i]-b[j])+ci[i]

    最后f[i]的状态转移方程即为:

      f[i]=f[j]+(sum[i]-sum[j])*xi[i]-(b[i]-b[j])+ci[i]

    斜率式的推导过程就不写了,最后可以化成:

      (f[j]+b[j]-f[k]-b[k])/(sum[j]-sum[k])<xi[i]-ci[i](k<j<i)

    //然而刚开始最后的那个加号写成乘号导致WA了两次,要注意队列的q[0]=0(不是1!!!),还是要细心吧。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long LL;
     5 const int maxn=1000010;
     6 using namespace std;
     7 LL xi[maxn],pi[maxn],ci[maxn],sum[maxn],b[maxn],f[maxn],q[maxn];
     8 inline LL read()
     9 {
    10     LL anss=0,f=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){anss=anss*10+c-48;c=getchar();}
    13     return anss*f;
    14 }
    15 inline double cal(LL a,LL bb)
    16 {
    17     return 1.0*(f[a]+b[a]-f[bb]-b[bb])/(sum[a]-sum[bb]);
    18 }
    19 int main()
    20 {
    21     int n;
    22     n=read();
    23     sum[0]=0;b[0]=0;
    24     for(int i=1;i<=n;i++){
    25         xi[i]=read();pi[i]=read();ci[i]=read();
    26         sum[i]=sum[i-1]+pi[i];
    27         b[i]=b[i-1]+xi[i]*pi[i];
    28     }
    29     int h=0,t=1;q[0]=0;f[0]=0;
    30     for(int i=1;i<=n;i++){
    31         while(h<t-1&&cal(q[h],q[h+1])<xi[i])h++;
    32         f[i]=f[q[h]]+(sum[i]-sum[q[h]])*xi[i]-(b[i]-b[q[h]])+ci[i];
    33         while(h<t-1&&cal(q[t-2],q[t-1])>cal(q[t-1],i))t--;
    34         q[t++]=i;
    35     }
    36     printf("%lld",f[n]);
    37     return 0;
    38 }
    bzoj1096
  • 相关阅读:
    展望2018
    Android按下home键后重新打开app进入主activity的问题
    RxJava整合Retrofit遇到的问题总结
    【总结】四种逆元的求法
    【NOIP模板汇总】I Am Me
    【总结】两类素数筛详解
    【NOIP2009】最优贸易
    【SHOI2002】滑雪
    【51NOD1398】等公交
    【复习总结】玫瑰人生 La Vie en Rose
  • 原文地址:https://www.cnblogs.com/JKAI/p/7465176.html
Copyright © 2020-2023  润新知