版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82432631
传送门
跟
为正数的时候差不多。
只是这个时候
数组没有了单调性,因此不能丢弃队头的元素,我们需要维护完整的下凸壳然后在上面二分。
写的时候如果用
函数算斜率好像会爆掉几个点,精度真神奇。。。
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 300005
using namespace std;
inline ll read(){
ll ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
int n,hd,tl,q[N];
ll S,tim[N],w[N],f[N];
inline double slope(int x,int y){return 1.0*(f[x]-f[y])/(1.0*(w[x]-w[y]));}
inline int find(ll cmp){
if(hd==tl)return q[hd];
int l=hd,r=tl;
while(l<r){
int mid=l+r>>1;
if(f[q[mid+1]]-f[q[mid]]<=cmp*(w[q[mid+1]]-w[q[mid]]))l=mid+1;
else r=mid;
}
return q[l];
}
int main(){
n=read(),S=read(),hd=1,tl=1;
for(int i=1;i<=n;++i)tim[i]=read()+tim[i-1],w[i]=read()+w[i-1];
for(int i=1;i<=n;++i){
int pos=find(S+tim[i]);
f[i]=f[pos]+S*(w[n]-w[pos])+tim[i]*(w[i]-w[pos]);
while(hd<tl&&(f[q[tl]]-f[q[tl-1]])*(w[i]-w[q[tl]])>=(f[i]-f[q[tl]])*(w[q[tl]]-w[q[tl-1]]))--tl;
q[++tl]=i;
}
cout<<f[n];
return 0;
}