1. 程式人生 > >—Libre#2009. 「SCOI2015」小凸玩密室

—Libre#2009. 「SCOI2015」小凸玩密室

有一個 orange prim rip math 點燈 time pan main

#2009. 「SCOI2015」小凸玩密室

內存限制:256 MiB時間限制:1000 ms標準輸入輸出 題目類型:傳統評測方式:文本比較 上傳者: 匿名 提交提交記錄統計討論測試數據

題目描述

小凸和小方相約玩密室逃脫,這個密室是一棵有 n nn 個節點的完全二叉樹,每個節點有一個燈泡。點亮所有燈泡即可逃出密室。每個燈泡有個權值 Ai A_iA?i??,每條邊也有個權值 bi b_ib?i??。

點亮第 1 11 個燈泡不需要花費,之後每點亮一個新的燈泡 V VV 的花費,等於上一個被點亮的燈泡 U UU 到這個點 V VV 的距離 D(u,v) D(u, v)D(u,v),乘以這個點的權值 Av A_vA?v??。

在點燈的過程中,要保證任意時刻所有被點亮的燈泡必須連通,在點亮一個燈泡後必須先點亮其子樹所有燈泡才能點亮其他燈泡。請告訴他們,逃出密室的最少花費是多少。

輸入格式

第一行包含一個數 n nn,代表節點的個數。
第二行包含 n nn 個數,代表每個節點的權值 ai a_ia?i??。
第三行包含 n−1 n - 1n1 個數,代表每條邊的權值 bi b_ib?i??,第 i ii 號邊是由第 i+12 \frac{i + 1}{2}?2??i+1?? 號點連向第 i+1 i + 1i+1 號點的邊。

輸出格式

輸出包含一個數,代表最少的花費。

樣例

樣例輸入

3
5 1 2
2 1

樣例輸出

5

數據範圍與提示

1≤N≤2×105,1<Ai,Bi≤105 1 \leq N \leq 2 \times 10 ^ 5, 1 < A_i, B_i \leq 10 ^ 51N2×10?5??,1<A?i??,B?i??10?5??

#include <cstdio>
#include <cstring>
#include 
<algorithm> using namespace std; const int N=200005,M=19; typedef long long LL; int n; LL a[N],b[N],dep[N],dis[N]; LL f[N][M],g[N][M],ans; char c; int read() { for (c=getchar();c<0 || c>9;c=getchar()); int x=c-48; for (c=getchar();c>=0 && c<=9;c=getchar()) x=x*10+c-48; return x; } int main(){ n=read(); for (int i=1;i<=n;i++) a[i]=read(); dep[1]=1; for (int i=2;i<=n;i++){ b[i]=read(); dep[i]=dep[i>>1]+1; dis[i]=dis[i>>1]+b[i]; } for (int i=n;i;i--){ for (int j=0;j<dep[i];j++){ int lca=(i>>(dep[i]-j)),x=(i>>(dep[i]-j-1))^1,lt=i<<1; if (lt>n) f[i][j]=(LL)a[x]*(dis[i]+dis[x]-dis[lca]*2); else if (lt==n) f[i][j]=(LL)a[lt]*b[lt]+f[lt][j]; else f[i][j]=min((LL)a[lt]*b[lt]+f[lt][dep[i]]+f[lt|1][j],(LL)a[lt|1]*b[lt|1]+f[lt|1][dep[i]]+f[lt][j]); } } for (int i=n;i;i--){ for (int j=0;j<dep[i];j++){ int x=i>>(dep[i]-j),lt=i<<1; if (lt>n) g[i][j]=(LL)a[x]*(dis[i]-dis[x]); else if (lt==n) g[i][j]=(LL)a[lt]*b[lt]+g[lt][j]; else g[i][j]=min((LL)a[lt]*b[lt]+f[lt][dep[i]]+g[lt|1][j],(LL)a[lt|1]*b[lt|1]+f[lt|1][dep[i]]+g[lt][j]); } } ans=g[1][0]; for (int i=2;i<=n;i++){ LL s=g[i][dep[i]-1]; for (int j=i;j>1;j>>=1){ int x=j^1,y=j>>1; if (x>n) s+=(LL)a[y>>1]*b[y]; else s+=(LL)a[x]*b[x]+g[x][dep[y]-1]; } if (s<ans) ans=s; } printf("%lld\n",ans); return 0; }

—Libre#2009. 「SCOI2015」小凸玩密室