大脑真是个很优秀的器官,做事情之前总会想着这太难,真的逼着自己做下去,回头看看,其实也不过如此
很朴素的斜率优化dp了
首先要读懂题目(我的理解能力好BUG啊)
然后设(dp[i])表示处理完前(i)个家伙,并且在第(i)个家伙处建仓的答案
那么有
[dp[i] = min_{j=1}^{i-1}{dp[j] + sum_{k=j+1}^{i-1} p[k] * (x[i] - x[k])} + c[i]
]
化简发现,优劣比较条件为
[frac{dp[p]-dp[q]+t[p]-t[q]}{s[p]-s[q]} < x[i]
]
于是就皆大欢喜啦
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n,x[N],p[N],c[N],s[N],t[N],f[N],q[N],l,r;
double slope(int k,int j) {
return 1.0 * (f[j]+t[j]-f[k]-t[k]) / (s[j]-s[k]);
}
signed main() {
scanf("%lld",&n);
for(int i=1;i<=n;i++) {
scanf("%lld%lld%lld",&x[i],&p[i],&c[i]);
s[i]=s[i-1]+p[i];
t[i]=t[i-1]+x[i]*p[i];
}
l=1; r=1;
for(int i=1;i<=n;i++) {
while(l<r && slope(q[l],q[l+1]) <= x[i]) ++l;
int j=q[l];
f[i] = f[j]+x[i]*(s[i]-s[j])-t[i]+t[j]+c[i];
while(l<r && slope(q[r-1],q[r]) >= slope(q[r],i)) --r;
q[++r]=i;
}
cout<<f[n]<<endl;
}