斜率优化模板,没什么好说的,如果不会斜率优化请戳这里。
原谅我水了一篇博客
当然注释还是会有的。
因为被卡了精度,所以需要把算斜率的公式变化一下,把除法移到另一边变成乘法即可。
代码如下:
#include <cstdio>
#include <cstring>
#define maxn 300010
int n,s;
int f[maxn],t[maxn],c[maxn];
int q[maxn],st(1),ed(1);
inline int up(int x,int y){return f[x]-f[y];}
inline int down(int x,int y){return c[x]-c[y];}
inline int calc(int x,int now){return f[x]+t[now]*(c[now]-c[x])+s*(c[n]-c[x]);}
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];
for(int i=1;i<=n;i++)
{
while(st<ed&&up(q[st+1],q[st])<(t[i]+s)*down(q[st+1],q[st]))st++;
//假如队列里面还有超过一个并且队首的两个的斜率比t[i]+s要小,那么q[st+1]肯定比q[st]要优,于是把q[st]踢掉
f[i]=calc(q[st],i);//计算当前这一位的值
while(st<ed&&up(q[ed],q[ed-1])*down(i,q[ed])>up(i,q[ed])*down(q[ed],q[ed-1]))ed--;
//因为要维护下凸包,所以斜率要递增,假如当前点i和队尾的斜率比队尾两个点的斜率要小
//那么此时不能将点i插入到队尾,那么就需要把此时的队尾踢掉
q[++ed]=i;
}
printf("%d",f[n]);
}