二刷提高课,题解目录在这里— 提高课的题解目录
此题和上题只有一个地方发生了变化那便是t可以取负数了
那说明我们的sumt不在具有单调性,也就是说我们的斜率存在后面的斜率比前面小的情况
那我们像单调队列那样去删去那些小斜率以达到不重复枚举的策略用不了了
但是我们寻找的还是第一个大于斜率的点的,所以我们可以进行二分来查找
而插入的时候因为c是大于零,x轴是单调递增的故我们还是要寻找一个不在凸包上的点
#include<iostream>
using namespace std;
typedef long long ll;
const int N=3e5+10;
ll sc[N],st[N];
ll f[N],q[N];
int n,s;
int main()
{
cin>>n>>s;
for(int i=1;i<=n;i++)
{
cin>>st[i]>>sc[i];
st[i]+=st[i-1];
sc[i]+=sc[i-1];
}
int hh=0,tt=0;
for(int i=1;i<=n;i++)
{
int l=hh,r=tt;
while(l<r)
{
int mid=l+r>>1;
if(f[q[mid+1]]-f[q[mid]]>=(st[i]+s)*(sc[q[mid+1]]-sc[q[mid]]))r=mid;
else l=mid+1;
}
int j=q[l];
f[i]=f[j]-(st[i]+s)*sc[j]+st[i]*sc[i]+s*sc[n];
while(hh<tt&&(double)(f[q[tt]]-f[q[tt-1]])*(sc[i]-sc[q[tt-1]])>=(double)(f[i]-f[q[tt-1]])*(sc[q[tt]]-sc[q[tt-1]]))tt--;//可能爆long long所以用double可以防止溢出
q[++tt]=i;
}
cout<<f[n];
return 0;
}