题解 P2365 【任务安排】
题解 P2365 【任务安排】
算法:斜率优化动态规划
由于题解里没有关于的斜率优化做法,我打算写一下这种特殊的斜率优化动态规划
由于可以小于零,所以斜率
不具有单调性,所以我们不能像原来一样维护下凸壳。我们不能只保留相邻两点斜率大于
的部分,我们要把整个下凸壳都保留下来。这时队首也就不是最优解了,要二分找到一个左边比
小,右边比
大的位置。这个位置就是答案
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=500005;
int l,r,n,s,t,c,j,sumt[N],sumc[N],f[N],q[N];
int find(int k)//二分查找左边比$s+sumt[i]$小,右边比$s+sumt[i]$大的位置
{
if(l==r)return q[l];
int L=l,R=r;
while(L<R)
{
int mid=(L+R)/2;
if(f[q[mid+1]]-f[q[mid]]<=k*(sumc[q[mid+1]]-sumc[q[mid]]))L=mid+1;
else R=mid;
}
return q[L];
}
signed main()
{
scanf("%lld%lld",&n,&s);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&t,&c);
sumt[i]=sumt[i-1]+t;
sumc[i]=sumc[i-1]+c;
}
l=r=1;q[1]=0;
for(int i=1;i<=n;i++)
{
int j=find(s+sumt[i]);//二分查找答案
f[i]=f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j]);
while(l<r&&(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])>=
(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]]))r--;//如果不构成下凸壳,就删除队尾
q[++r]=i;
}
cout<<f[n]<<endl;
} xuxuxuxuxu 文章被收录于专栏
信息学竞赛

