这题首先要转化一下这里对于 (s) 的统计
我们先把 (s) 做后缀贡献
然后就有了这个式子:
[f_i=min_{j=1}^{i-1} f_j+ (s1_i-s1_j) imes s2_i+s imes(s1_n-s1_j)
]
其中
[s1_i=sum_{j=1}^{i-1} c_j s2_i=sum_{j=1}^{i-1} t_j
]
然后我们推式子:
最后是个:
(x<y) 且
[frac{(f_x-s imes s1_x)-(f_y-s imes s1_y)}{s1_x-s1_y}<s2_i
]
右侧是个单调增的,所以是个下凸壳
然后就没了
如果我们不保证 (t_i) 单调呢?
我们照样维护一个下凸壳
然后每次在这里面找决策点的时候二分一下
具体见代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=3e5+10;
int t[N],c[N],n,s,f[N],q[N],he,ta;
inline double X(int p){return c[p];}
inline double Y(int p){return f[p]-s*c[p];}
inline double slope(int x,int y){ return (Y(y)-Y(x))/(X(y)-X(x)); }
inline int work(double val)
{
int l=he,r=ta-1,ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(Y(q[mid])-Y(q[mid+1])<val*(X(q[mid])-X(q[mid+1]))) ans=mid,r=mid-1;
else l=mid+1;
}
if(ans==-1) return q[ta];
else return q[ans];
}
signed main()
{
n=read(); s=read();
for(int i=1;i<=n;++i) t[i]=read()+t[i-1],c[i]=read()+c[i-1];
for(int i=1;i<=n;++i)
{
int tmp=work(t[i]);
f[i]=f[tmp]+t[i]*(c[i]-c[tmp])+s*(c[n]-c[tmp]);
while(he<ta&&(Y(q[ta-1])-Y(q[ta]))*(X(q[ta])-X(i))>=(Y(q[ta])-Y(i))*(X(q[ta-1])-X(q[ta]))) ta--;
q[++ta]=i;
}
printf("%lld
",f[n]);
return 0;
}
}
signed main(){return yspm::main();}