説明
小さな正方形と小突起類似プレイエスケープ室は、この室がある\(\ N-)完全二分木のノード、各ノードは、電球を有します。すべての球根は、秘密の部屋を脱出するために点灯することができます。各ランプは、重量た\(AI \)は、各側は、重量有する\(BIを\) 。ランプの点灯は、それぞれの新しい点灯後、ランプ取らない\(Vの\)を費やし、それは照明電球に等しい\(U- \)ポイントに\(Vの\)距離\(DU、V \) 、ポイントの重みを乗算\(AV \) 。点灯中、すべての通信は、ランプバルブを他のすべてのランプを点灯するために照明サブツリーの後に点灯されなければならない電球を点灯しなければならないことを保証するために、いつでも。
少なくともそれは秘密の部屋エスケープ過ごすためにそれらを教えてください。
入力
ライン1は、多数の含有\(N-を\) 、代表内のノードの数
ライン2が含まれている\(N- \)数、各ノードの重みのための代表的な値\(AI \)を。(\(I = 1,2、...、N-\) )
3行目は含ま\(N-1 \)数、各エッジの値の表現\(BI \) 、最初の\(Iは\)号エッジ最初は、((I + 1)/ \ 2 \) ドットが第二に接続されている\(I + 1 \)ドットの側面。(\(L = I、2、... 1-N \) )
出力
図1は、最も安価を表す出力数を、含みます。
サンプル入力
3
5 1 2
2 1
サンプル出力
5
ヒント
以下のための\(100 \%の\)データ、\(1 \のLeq N \のLeq 2 \ ^ 10 5回\)、\ (Biの\の1 <あい、1当量5 ^ 10 \)
考え
クリアツリー\(DP \) 。
しかし、ピット内の2つの問題に注意を払います!!!!!!
最初のノードは、必ずしも照明ポイント1ではありません!
「完全なバイナリツリーは、」最初の意味\を(私は\)父親ポイント\を(I / 2 \)が、すべての非リーフノードは2人の子供を持っていることを保証するものではありません!
まず最初のポイントが点灯していることを前提としています。
次いで、ツリー\(DP \)のステータス:
\(DP [I] [J]が\)電流を表し\(Iは\)が点灯されているが、点灯を開始する(Iは\)\サブツリーのルートであり、そのフル点灯した後、最後のポイントは、に行きました(j個の\を)\点灯する\(J \)最小コストを。
転送は、最初の行に点灯して子供についてどのようなメモリの検索を考慮し、また、非常に明白です。
このケースであるため、すべてのために\(私は\) 、便利な\(DP [I] [J ] \) で\(j個\)別の子、すべての先祖のために過ぎない\(O (LOGN)\)ヶ月なので、状態の総数\(O(nlogn)\) 、タイムアウトしません。
、サーブ最初の有料\(WA \) A。
ルートが変わり始めました。
最初のポイントライトの場合、または点灯しているサブツリーにそれを置くために、その親を点灯。
そして、それぞれの\(私は\) 、便利な\(DP [I] [J ] \) で\(j個\)他のすべての子供たちの祖先に加えて、だけでなく、その祖先のすべてが、それでも\( O(LOGN)\)レベル、総複雑\(O(nlogn)\) 。
メモリ検索した後、タイムアウトした(qwq \)\を
これは、メモリのではありません(使用して\(地図\)の定数は[彼の後ろに]は大きすぎる)
\ -再配置された状態
(F [I] [J] \)を表す\(DP [I] [Y] \)を、前記\(Y \)がある\(Iは\)の\(J + 1 \)祖先。
\(G [I] [J ] \)を表す\(DP [I] [Z] \) 、\(Zの\)の\(Iは\)の\(J + 1 \)は、別の祖先子どもたち。
\(O(nlogn)\)時間は、これらの値は、バックルートに次に計算され、することができます。
、サーブ最初の有料\(WA \) A。
それはないすべての非リーフノードは、2人の子供を持っていることがわかったので、彼は詳細を変更するように変更しました。最後に\(\)アウト!
コード
非常に恐れて、[詳細]
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int read(){
int x=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x;
}
const int N = 200005;
typedef long long ll;
int n,a[N],b[N];
ll f[N][20],g[N][20];
ll ans;
void dfs(int x,ll cur){ //换根
int l=x*2,r=x*2+1;
if(x!=1){
ll now;
if(r<=n) now=min(1ll*a[l]*b[l]+g[l][0]+f[r][1],1ll*a[r]*b[r]+g[r][0]+f[l][1]);
else if(l==n) now=1ll*a[l]*b[l]+f[l][1];
else now=f[x][0];
ans=min(ans,now+cur);
}
if(l>n) return;
if(l==n) dfs(l,cur+1ll*b[x]*a[x/2]);
else{
dfs(l,cur+1ll*a[r]*b[r]+f[r][1]);
dfs(r,cur+1ll*a[l]*b[l]+f[l][1]);
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=2;i<=n;i++) b[i]=read();
for(int i=n;i>0;i--){
if(i*2>n){
int x=i/2,last=(i&1) ? i-1 : i+1;
ll s=b[i];
for(int j=0;x>=0;j++,x/=2){
f[i][j]=s*a[x];
g[i][j]=1ll*(s+b[last])*a[last];
s+=b[x]; last=(x&1) ? x-1 : x+1;
if(x==0) break;
}
continue;
}
else if(i*2==n){
for(int j=0,x=i/2;x>=0;j++,x/=2){
f[i][j]=1ll*a[n]*b[n]+f[n][j+1];
g[i][j]=1ll*a[n]*b[n]+g[n][j+1];
if(x==0) break;
}
continue;
}
int l=i*2,r=l+1;
for(int j=0,x=i/2;x>=0;j++,x/=2){
f[i][j]=min(1ll*a[l]*b[l]+g[l][0]+f[r][j+1],1ll*a[r]*b[r]+g[r][0]+f[l][j+1]);
g[i][j]=min(1ll*a[l]*b[l]+g[l][0]+g[r][j+1],1ll*a[r]*b[r]+g[r][0]+g[l][j+1]);
if(x==0) break;
}
}
ans=f[1][0];
dfs(1,0);
printf("%lld\n",ans);
return 0;
}