传送门
SOL:
标准的斜率优化板题。
dp方程:
f [ i ] = m i n ( f [ j ] + ( s [ i ] − s [ j ] ) ∗ t [ i ] ) + S ∗ ( s [ n ] − s ] j ] ) f[i]=min(f[j]+(s[i]-s[j])*t[i])+S*(s[n]-s]j]) f[i]=min(f[j]+(s[i]−s[j])∗t[i])+S∗(s[n]−s]j])
注意此处存储前面S的总数,可以在当前先计算了后面会产生的代价,提前分开算
(拆分贡献的思想)
但是T不单调,所以要在下凸的四边形上二分找到 k p r e < = k n o w k_{pre}<=k_{now} kpre<=know && k a f t e r > k n o w k_{after}>k_{now} kafter>know
CODE:
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define int long long
using namespace std;
const int maxn=3e5+10;
int f[maxn],s[maxn],t[maxn],S,n;
int head,tail,q[maxn];
/*
f[j]=(t[i]+S)*s[j]-S*s[n]-s[i]*t[i]+f[i];
f[i]=f[j]+(s[i]-s[j])*t[i]+ S*(s[n]-s[j])
t[i]+S 不单调,所以二分
*/
inline int find(int k){
if(head==tail)return q[head];
int l=head,r=tail;
while(l<r){
int mid=(l+r)>>1;
if((f[q[mid+1]]-f[q[mid]])<=k*(s[q[mid+1]]-s[q[mid]]))l=mid+1;
else r=mid;
}
return q[l];
}
signed main (){
sf("%lld%lld",&n,&S);
for(int i=1;i<=n;++i)sf("%lld%lld",&t[i],&s[i]),t[i]+=t[i-1],s[i]+=s[i-1];
head=tail=1;
f[0]=0;s[0]=0;
for(int i=1;i<=n;++i){
int j=find(t[i]+S);
f[i]=f[j]+1ll*(s[i]-s[j])*t[i]+1ll*S*(s[n]-s[j]);
while(head<tail&&(f[q[tail]]-f[q[tail-1]])*(s[i]-s[q[tail]])>=(f[i]-f[q[tail]])*(s[q[tail]]-s[q[tail-1]]))--tail;
q[++tail]=i;
}
cout<<f[n];
return 0;
}