分析
dp方程显然是
d
p
[
i
]
=
min
{
d
p
[
j
]
+
∑
k
=
j
+
1
i
p
[
k
]
(
x
[
i
]
−
x
[
k
]
)
}
+
c
[
i
]
dp[i]=\min\{dp[j]+\sum_{k=j+1}^ip[k](x[i]-x[k])\}+c[i]
dp[i]=min{dp[j]+k=j+1∑ip[k](x[i]−x[k])}+c[i]
考虑维护
p
[
i
]
x
[
i
]
,
p
[
i
]
p[i]x[i],p[i]
p[i]x[i],p[i]的前缀和
s
,
s
u
m
s,sum
s,sum,那么式子可以化成
d
p
[
i
]
=
min
{
d
p
[
j
]
+
x
[
i
]
(
s
u
m
[
i
]
−
s
u
m
[
j
]
)
−
(
s
[
i
]
−
s
[
j
]
)
}
dp[i]=\min\{dp[j]+x[i](sum[i]-sum[j])-(s[i]-s[j])\}
dp[i]=min{dp[j]+x[i](sum[i]−sum[j])−(s[i]−s[j])}
若
k
(
j
<
k
)
k(j<k)
k(j<k)更优于
j
j
j,那么
d
p
[
j
]
+
x
[
i
]
(
s
u
m
[
i
]
−
s
u
m
[
j
]
)
−
(
s
[
i
]
−
s
[
j
]
)
>
d
p
[
k
]
+
x
[
i
]
(
s
u
m
[
i
]
−
s
u
m
[
k
]
)
−
(
s
[
i
]
−
s
[
k
]
)
dp[j]+x[i](sum[i]-sum[j])-(s[i]-s[j])>dp[k]+x[i](sum[i]-sum[k])-(s[i]-s[k])
dp[j]+x[i](sum[i]−sum[j])−(s[i]−s[j])>dp[k]+x[i](sum[i]−sum[k])−(s[i]−s[k])
那么简化可以得到
d
p
[
j
]
−
x
[
i
]
s
u
m
[
j
]
+
s
[
j
]
>
d
p
[
k
]
−
x
[
i
]
s
u
m
[
k
]
+
s
[
k
]
dp[j]-x[i]sum[j]+s[j]>dp[k]-x[i]sum[k]+s[k]
dp[j]−x[i]sum[j]+s[j]>dp[k]−x[i]sum[k]+s[k]
那么
d
p
[
k
]
−
x
[
i
]
s
u
m
[
k
]
+
s
[
k
]
<
d
p
[
j
]
−
x
[
i
]
s
u
m
[
j
]
+
s
[
j
]
dp[k]-x[i]sum[k]+s[k]<dp[j]-x[i]sum[j]+s[j]
dp[k]−x[i]sum[k]+s[k]<dp[j]−x[i]sum[j]+s[j]
d
p
[
k
]
−
d
p
[
j
]
+
s
[
k
]
−
s
[
j
]
s
u
m
[
k
]
−
s
u
m
[
j
]
<
x
[
i
]
\frac{dp[k]-dp[j]+s[k]-s[j]}{sum[k]-sum[j]}<x[i]
sum[k]−sum[j]dp[k]−dp[j]+s[k]−s[j]<x[i]
由于距离是单调递增的,所以维护下凸壳
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=1000001;
int n,dis[N],q[N],c[N]; long long sum[N],s[N],dp[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline double slope(int j,int k){
return 1.0*(dp[k]+sum[k]-dp[j]-sum[j])/(s[k]-s[j]);
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i){
dis[i]=iut(),sum[i]=iut(),c[i]=iut(),
s[i]=s[i-1]+sum[i],sum[i]=sum[i-1]+sum[i]*dis[i];
}
rr int head=1,tail=0; q[++tail]=0;
for (rr int i=1;i<=n;++i){
while (head<tail&&slope(q[head],q[head+1])<dis[i]) ++head;
dp[i]=dp[q[head]]+c[i]+(s[i]-s[q[head]])*dis[i]-sum[i]+sum[q[head]];
while (head<tail&&slope(q[tail-1],q[tail])>slope(q[tail],i)) --tail;
q[++tail]=i;
}
return !printf("%lld",dp[n]);
}