题解 P2365 【任务安排】
ButterflyDew · · 题解
其他题解里面的斜率优化讲的对新手不友好,我详细说一下吧
欢迎到博客食用喵~
先考虑
因为分的批数是不定的,所有我们为了避免算后面的时候要用到前面分了多少批这个状态,我们采用费用提前的思想,在处理前面时把
方程:
转移:
考虑将状态转移方程化简:
注意:我们这里把
那么这个一次函数的斜率
我们想让这个
1.考虑什么时候一个点可以取到最小值
通过手玩我们发现(对于这个手玩真的是最好的理解方式了)
对于点
当斜率
2.考虑什么时候一个点可能可以取到最小值,什么时候一定不能
如下图,当斜率
当斜率
此时我们就可以用单调队列维护一个点集了,其中相邻点的斜率
当需要做出决策的时候,我们二分这个点集,找到最优转移点。
针对于此题,我们发现每个决策点的斜率
统计完答案后再用二元组
Code:
#include <cstdio>
#include <cstring>
const int N=5010;
int f[N],t[N],c[N],n,S,q[N],l,r;
int main()
{
scanf("%d%d",&n,&S);
for(int i=1;i<=n;i++)
{
scanf("%d%d",t+i,c+i);
t[i]+=t[i-1];
c[i]+=c[i-1];
}
memset(f,0x3f,sizeof(f));
f[0]=0;
l=1,r=1;//注意此时已经把0作为元素放入了q[1]中去了
for(int i=1;i<=n;i++)
{
while(l<r&&f[q[l+1]]-f[q[l]]<=(S+t[i])*(c[q[l+1]]-c[q[l]])) l++;
f[i]=f[q[l]]+t[i]*c[i]+S*c[n]-c[q[l]]*(S+t[i]);
while(l<r&&(f[i]-f[q[r]])*(c[q[r]]-c[q[r-1]])<=(f[q[r]]-f[q[r-1]])*(c[i]-c[q[r]])) r--;
q[++r]=i;
}
printf("%d\n",f[n]);
return 0;
}