笔记-[ZJOI2007]仓库建设
笔记-[ZJOI2007]仓库建设
\(f_i\) 到第 \(i\) 个工厂并且建设了仓库。
\[\begin{split}
f_i=&\min\{f_j+\sum_{h=j+1}^ip_h(x_i-x_h)\}+c_i\\
=&\min\{f_j+\sum_{h=j+1}^i\left(p_hx_i-p_hx_h\right)\}+c_i\\
\end{split}
\]
设 \(s_i=\sum_{h=1}^i p_h\),\(S_i=\sum_{h=1}^i p_hx_h\)。
\[\begin{split}
f_i=&\min\{f_j+\sum_{h=j+1}^i\left(p_hx_i-p_hx_h\right)\}+c_i\\
=&\min\{f_j+x_i(s_i-s_j)-(S_i-S_j)\}+c_i\\
=&\min\{f_j-x_is_j+S_j\}+x_is_i-S_i+c_i\\
\end{split}
\]
考虑 \(j=k\) 比 \(j=t\) 更优:
\[\begin{split}
f_k-x_is_k+S_k<& f_t-x_is_t+S_t\\
(f_k+S_k)-(f_t+S_t)<& x_is_k-x_is_t\\
\frac{(f_k+S_k)-(f_t+S_t)}{s_k-s_t}<& x_i\\
\end{split}
\]
搞定。
Code
#include <bits/stdc++.h>
using namespace std;
//Start
#define re register
#define il inline
#define mk make_pair
#define pb push_back
#define db double
#define lng long long
#define fi first
#define se second
const int inf=0x3f3f3f3f;
const lng INF=0x3f3f3f3f3f3f3f3f;
//Data
int n;
vector<int> x,p,c;
vector<lng> s,S,f;
//DP
il db slope(re int k,re int t){
return 1.0*((f[k]+S[k])-(f[t]+S[t]))/(s[k]-s[t]);
}
il int DP(){
re int l=1,r=0; re vector<int> q(n+7); q[++r]=0;
for(re int i=1;i<=n;i++){
while(l<r&&slope(q[l],q[l+1])<=x[i]) l++;
f[i]=f[q[l]]-(lng)x[i]*s[q[l]]+S[q[l]]+(lng)x[i]*s[i]-S[i]+c[i];
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) r--;
q[++r]=i;
}
return f[n];
}
//Main
int main(){
scanf("%d",&n);
x=p=c=vector<int>(n+7);
s=S=f=vector<lng>(n+7);
for(re int i=1;i<=n;i++){
scanf("%d%d%d",&x[i],&p[i],&c[i]);
s[i]=s[i-1]+p[i],S[i]=S[i-1]+(lng)p[i]*x[i];
}
printf("%lld\n",DP());
return 0;
}
\[\Huge\color{#ddd}{\texttt{---END---}}
\]