【CEOI2017】Building Bridges【任意坐标斜率优化】【李超线段树】
題意:有 nnn 個柱子,每個柱子有高度 hih_ihi?。你需要在柱子間修橋,在 i,ji,ji,j 間修橋代價為 (hi?hj)2(h_i-h_j)^2(hi??hj?)2,橋梁只能在柱子處相交,未安裝橋的柱子需要拆除,代價為 wiw_iwi?(可能為負數)。求讓 111 和 nnn 連接的最小代價。
n≤105,hi,∣wi∣≤106n\leq 10^5,h_i,|w_i|\leq 10^6n≤105,hi?,∣wi?∣≤106
顯然是斜率優化
設 fif_ifi? 表示從 111 修到 iii 的最小代價,sss 為 www 前綴和。
fi=min?1≤j<i{fj+(hi?hj)2+si?1?sj}f_i=\min_{1\leq j<i}\{f_j+(h_i-h_j)^2+s_{i-1}-s_j\}fi?=1≤j<imin?{fj?+(hi??hj?)2+si?1??sj?}
fi=min?1≤j<i{fj+hi2?2hihj+hj2+si?1?sj}f_i=\min_{1\leq j<i}\{f_j+h^2_i-2h_ih_j+h^2_j+s_{i-1}-s_j\}fi?=1≤j<imin?{fj?+hi2??2hi?hj?+hj2?+si?1??sj?}
fi=hi2+si?1+min?1≤j<i{?2hj?hi+fj+hj2?sj}f_i=h^2_i+s_{i-1}+\min_{1\leq j<i}\{-2h_j\cdot h_i+f_j+h_j^2-s_j\}fi?=hi2?+si?1?+1≤j<imin?{?2hj??hi?+fj?+hj2??sj?}
每個決策 jjj 看成斜率為 ?2hj-2h_j?2hj?,截距為 fj+hj2?sjf_j+h_j^2-s_jfj?+hj2??sj? 的直線, hih_ihi? 看成自變量,李超線段樹求最小值即可。
復雜度 O(nlog?n)O(n\log n)O(nlogn)
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> using namespace std; const int N=1e6,MAXN=N+5; typedef long long ll; inline int read() {int ans=0,f=1;char c=getchar();while (!isdigit(c)) (c=='-')&&(f=-1),c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return f*ans; } ll k[MAXN],b[MAXN]; inline ll calc(int i,int x){return k[i]*x+b[i];} #define lc p<<1 #define rc p<<1|1 int mn[MAXN<<2]; void modify(int p,int l,int r,int v) {int mid=(l+r)>>1;if (!mn[p]) return (void)(mn[p]=v);if (calc(mn[p],l)<=calc(v,l)&&calc(mn[p],r)<=calc(v,r)) return;if (calc(mn[p],l)>=calc(v,l)&&calc(mn[p],r)>=calc(v,r)) return (void)(mn[p]=v);if (calc(mn[p],mid)>calc(v,mid)) swap(mn[p],v);if (calc(mn[p],l)>calc(v,l)) modify(lc,l,mid,v);else modify(rc,mid+1,r,v); } void query(int p,int l,int r,int k,ll& ans) {if (mn[p]) ans=min(ans,calc(mn[p],k));if (l==r) return;int mid=(l+r)>>1;if (k<=mid) query(lc,l,mid,k,ans);else query(rc,mid+1,r,k,ans); } ll h[MAXN],s[MAXN],f[MAXN]; int main() {int n=read();for (int i=1;i<=n;i++) h[i]=read();for (int i=1;i<=n;i++) s[i]=s[i-1]+read();k[1]=-2*h[1],b[1]=h[1]*h[1]-s[1];modify(1,0,N,1);for (int i=2;i<=n;i++){query(1,0,N,h[i],f[i]=1e18);f[i]+=h[i]*h[i]+s[i-1];k[i]=-2*h[i],b[i]=h[i]*h[i]+f[i]-s[i];modify(1,0,N,i);}cout<<f[n];return 0; }總結
以上是生活随笔為你收集整理的【CEOI2017】Building Bridges【任意坐标斜率优化】【李超线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 如何访问ipv6网站
 - 下一篇: 《暴力辛迪加》详细图文视频流程攻略