P4655 [CEOI2017] Building Bridges 题解

P4655

分析

发现如果在 \(i,j\) 之间建桥,那么 \((i,j)\) 内的所有柱子都是无用的,代价还需加上 \((i,j)\) 内的所有拆除代价。设 \(dp_i\) 为从 \(1\) 走到 \(i\) 的最小代价,于是转移方程就呼之欲出了:

\[dp_i=\min\limits_{j=1}^{i-1}\{dp_j+(h_i-h_j)^2+s_{i-1}-s_j\} \]

,其中 \(s_i\) 表示拆除代价的前缀和。发现如果枚举每一个 \(j\) 时间复杂度是 \(\mathcal{O}(n^2)\),显然会 TLE,因此考虑优化。发现这个式子是很典型的斜率优化形式,可以变形为:

\[dp_i=\min\limits_{j=1}^{i-1}\{dp_j-2h_ih_j+h_j^2-s_j\}+h_i^2+s_{i-1} \]

然而发现每次查询的斜率并不是有序的,因此不能直接单调队列维护凸包。发现数据范围只到 \(10^5\),用李超线段树可以方便的求出当 \(x=h_i\) 时最小的 \(y\),于是就可以做了。时间复杂度 \(\mathcal{O}(n\log n)\)

核心代码

qread(n);int i,j,mx=0;for(i=1;i<=n;i++) qread(h[i]),mx=qmax(mx,h[i]);
build(1,0,mx);for(i=1;i<=n;i++) qread(w[i]),w[i]+=w[i-1];
dp[1]=0;upd(1,0,mx,Line{-2*h[1],h[1]*h[1]-w[1]});
for(i=2;i<=n;i++){
    dp[i]=que(1,0,mx,h[i])+h[i]*h[i]+w[i-1];
    upd(1,0,mx,Line{-2*h[i],dp[i]+h[i]*h[i]-w[i]});
}printf("%lld\n",dp[n]);

record

posted @ 2022-09-13 11:21  l_x_y  阅读(37)  评论(0编辑  收藏  举报