• Jzoj3169 生产汽车


    如前面提到,ABC的汽车工厂有N个工人,他们在一个传送带上生产汽车,工人从左到右排列,编号依次为1到N,采用流水线模式,每个人负责自己的一部分工作。

    生产一台汽车需要从1号工人开始,当1号完成他的工作后,2号就会开始工作,然后是3号,最后当N号工人完成他的工作后,整个汽车生产完毕。工人们一共需要生产M台汽车,而且必须按照从1到M的顺序去生产。

    对于工人i,他完成自己的工作需要Ti的时间,而对于汽车j,组装复杂度为Fj。那么工人i花在汽车j上的时间为Ti*Fj。

    当某个工人完成他的工作后,他会同时把汽车交给下一个工人,没有任何时间上的延迟,因此,要保证下一个要接受汽车的工人必须是空闲的。为了满足这个要求,ABC需要为每一台汽车选择一个好时机开始制造。

    ABC想知道生产完所有汽车最少需要多少时间。

    先来考虑O(n^2)的情况

    我们令g[i]表示第i辆汽车开始生产的时间,g[1]=0

    那么g[i]=g[i-1]+max(f[i-1]*sum[j]+f[i]*sum[j-1]) 其中sum[j]=Σt[k] (1<=k<=j)

    这里表示每一个人都必须在它生产完i-1这辆车之后才能继续第i辆,看到这个式子我们可以考虑斜率优化

    对于决策j,k若k优于j那么就有

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

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

    f[i-1]/f[i]<(s[j-1]-s[k-1])/(s[j]-s[k])

    因为f[i-1]/f[i]不单调,所以我们维护一个斜率单调递减的上凸壳,让后在上面二分

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 100010
    using namespace std;
    int n,m,q[N],t=0;
    long long f[N],s[N],g[N];
    inline double slp(int i,int j){ 
    	return (s[i]-s[j])/(double)(s[i-1]-s[j-1]);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		scanf("%lld",s+i),s[i]+=s[i-1];
    	for(int i=1;i<=m;++i) scanf("%lld",f+i);
    	for(int i=1;i<=n;++i){
    		for(;t>1&&slp(i,q[t])>slp(q[t],q[t-1]);--t);
    		q[++t]=i;
    	}
    	g[1]=0;
    	for(int i=2,l,r,M;i<=m;++i){
    		l=0; r=t; 
    		for(double k=f[i]/(double)f[i-1];l<r;){
    			M=l+r>>1;
    			if(slp(q[M+1],q[M])>k) l=M+1; else r=M;
    		}
    		g[i]=g[i-1]+s[q[l]]*f[i-1]-s[q[l]-1]*f[i];
    	}
    	printf("%lld
    ",1ll*g[m]+s[n]*f[m]);
    }

  • 相关阅读:
    使用Mybatis时报错Invalid bound statement (not found):
    MyBatis学习(3)
    选数字
    看程序写结果
    NP
    完全平方数
    hahaha
    haha

    凝视
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477158.html
Copyright © 2020-2023  润新知