我们显然有n^2 dp
其中
然后我们斜率优化一波,设k1< k2,且k2优于k1
但是因为t可以为负数,不单调,于是我们只能cdq分治+斜率优化搞了。
维护上凸壳,提前把询问按斜率排序,直接拿指针扫一遍凸壳即可。两个凸壳合并起来也可以归并做到
复杂度
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define inf 1e20
#define N 300010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,S,t[N],w[N],q[N];
struct Icefox{
int x,k,id;
ll y,f;
inline bool friend operator<(Icefox a,Icefox b){return a.id<b.id;}
}a[N],b[N];
inline bool cmpk(Icefox a,Icefox b){return a.k>b.k;}
inline ld slope(int k1,int k2){
if(a[k1].x==a[k2].x) return a[k2].y>=a[k1].y?inf:-inf;
return ((ld)a[k2].y-a[k1].y)/(a[k2].x-a[k1].x);
}
inline void solve(int l,int r){
if(l==r){a[l].y=(ll)(a[l].k-S)*a[l].x-a[l].f;return;}
int mid=l+r>>1,p1=l,p2=mid+1;
for(int i=l;i<=r;++i){
if(a[i].id<=mid) b[p1++]=a[i];
else b[p2++]=a[i];
}memcpy(a+l,b+l,sizeof(a[0])*(r-l+1));
solve(l,mid);int qh=1,qt=0;
for(int i=l;i<=mid;++i){
while(qh<qt&&slope(q[qt],i)>=slope(q[qt-1],q[qt])) --qt;
q[++qt]=i;
}for(int i=mid+1;i<=r;++i){
while(qh<qt&&slope(q[qh],q[qh+1])>=a[i].k) ++qh;
a[i].f=min(a[i].f,a[q[qh]].f+(ll)(S+a[i].k-a[q[qh]].k)*a[q[qh]].x);
}solve(mid+1,r);p1=l,p2=mid+1;
for(int i=l;i<=r;++i){
if(p2>r||a[p1].x<=a[p2].x) b[i]=a[p1++];
else b[i]=a[p2++];
}memcpy(a+l,b+l,sizeof(a[0])*(r-l+1));
}
int main(){
// freopen("a.in","r",stdin);
n=read();S=read();
for(int i=1;i<=n;++i) t[i]=read(),w[i]=read();
for(int i=1;i<=n;++i) t[i]+=t[i-1],a[i].k=t[i];
for(int i=n;i>=1;--i) w[i]+=w[i+1],a[i].x=w[i+1];
for(int i=1;i<=n;++i) a[i].f=(ll)(S+t[i])*w[1],a[i].id=i;
sort(a+1,a+n+1,cmpk);
solve(1,n);sort(a+1,a+n+1);
printf("%lld\n",a[n].f);
return 0;
}