版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/89280993
有 个人和 辆汽车,第 个人可以完成第 辆车的第 项工序,耗时
现在必须要从前往后造汽车,但是当 完成他的工序时, 这个人必须有空闲去接上他的工序
求最快完成的时间。
数据范围:
设 表示第 辆汽车开始生产的时间,
表示每个人都必须在它生产完 这辆车之后才能继续第 辆,看到这个十字我们考虑斜率优化
对于决策 若 优于 ,那么有
分配率
等式的性质
但是 不具有单调性,所以我们维护一个斜率单调递减的上凸壳,然后在上面二分
#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define N 100010
using namespace std;
int n,m,q[N],t=0;
long long F[N],s[N],f[N];
inline long long read()
{
char c;int f=0,d=1;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline double slp(int i,int j)
{
return (s[i]-s[j])/(double)(s[i-1]-s[j-1]);//斜率
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i) s[i]=s[i-1]+read();
for(int i=1;i<=m;++i) F[i]=read();
for(int i=1;i<=n;++i)
{
for(;t>1&&slp(i,q[t])>slp(q[t],q[t-1]);--t);//维护一个斜率单调递减的上凸壳
q[++t]=i;//放入队尾
}
f[1]=0;
for(int i=2,l,r,mid;i<=m;++i)
{
l=0; r=t;
for(double k=F[i]/(double)F[i-1];l<r;)//二分找到最优决策点
{
mid=l+r>>1;
if(slp(q[mid+1],q[mid])>k) l=mid+1; else r=mid;
}
f[i]=f[i-1]+s[q[l]]*F[i-1]-s[q[l]-1]*F[i];//利用最优决策算出答案
}
printf("%lld\n",1ll*f[m]+s[n]*F[m]);
}