Description
机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1,2,3…N。这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和。注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。
【题目分析】
斜率优化+二分。
【代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
long long f[1000002],t[1000002],que[1000002],dp[1000002];
long long hd,tl,n,s;
inline long long read()
{
long long 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;
}
int main()
{
n=read();s=read();
for (long long i=1;i<=n;++i)
{
t[i]=read();f[i]=read();
t[i]+=t[i-1];
f[i]+=f[i-1];
}
memset(dp,0x3f,sizeof dp);
dp[0]=0;hd=0;tl=0;
que[hd]=0;
for (long long i=1;i<=n;++i)
{
long long l=0,r=tl;
while (l<r)
{
long long mid=(l+r)/2;
if ((double)dp[que[mid+1]]-dp[que[mid]]>=(double)(s+t[i])*(f[que[mid+1]]-f[que[mid]])) r=mid;
else l=mid+1;
}
dp[i]=min(dp[i],dp[que[l]]+(f[i]-f[que[l]])*t[i]+s*(f[n]-f[que[l]]));
while(hd<tl&&(dp[i]-dp[que[tl]])*(f[que[tl]]-f[que[tl-1]])<=(dp[que[tl]]-dp[que[tl-1]])*(f[i]-f[que[tl]])) tl--;
que[++tl]=i;
}
printf("%lld\n",dp[n]);
}