只是来除个草。。
这和当年CH上某cf赛制的题的B题很像。不过是这个的弱化版。
令f[i]表示第i个上面建仓库,1~i的都处理好了之后的最小花费。
那么f[i]=min{f[j]+w(j,i)}+c[i]
然后把w(j,i)化开:=p[j]*(x[i]-x[j])+p[j+1]*(x[i]-x[j+1])+...+p[i]*(x[i]-x[i])
=x[i]*p[j..i]-p[j]*x[j]+p[j+1]*x[j+1]+...+p[i]*x[i]
很明显前后两项都可以用前缀和数组O(1)出来。sp[i]=p[1..i],spx[i]=p[1]*x[1]+..+p[i]*x[i]
可惜这样还是n^2的。n还是100w这么凶残。
那么考虑斜率优化。
把w(j,i)带进去。
f[i]=min{f[j]+x[i](sp[i]-sp[j])-spx[i]+spx[j]}+c[i];
可以发现决策有单调性,x=sp[i]-sp[j],y=f[j]-spx[i]+spx[j],k=x[i]。那么就行了。O(n)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double D;
const int maxn=1000005;
const double inf=1e30;
ll x[maxn],p[maxn],c[maxn],sp[maxn],spx[maxn],q[maxn],f[maxn];
inline D slope(int i,int j){
ll dx=sp[i]-sp[j],dy=f[i]-f[j]+spx[i]-spx[j];
if(!dx) return (dy>=0)?inf:-inf;
return (D)dy/(D)dx;
}inline void read(ll &x){
ll r=0,f=1;char ch;
for(ch=getchar();(ch!='-')&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-') f=-1; else r=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar())r=r*10+ch-48;
x=r*f;
}int main(){
ll n;read(n);
for(ll i=1;i<=n;i++){
read(x[i]);read(p[i]);read(c[i]);
sp[i]=sp[i-1]+p[i];
spx[i]=spx[i-1]+p[i]*x[i];
}ll s=0,e=0;q[0]=0;
for(ll i=1;i<=n;i++){
while(s<e&&slope(q[s],q[s+1])<=(D)x[i])s++;
f[i]=f[q[s]]+x[i]*(sp[i]-sp[q[s]])-(spx[i]-spx[q[s]])+c[i];
while(s<e&&slope(q[e],q[e-1])>=slope(i,q[e]))e--;
q[++e]=i;
}printf("%lld\n",f[n]);
return 0;
}