bzoj4446[Scoi2015]小凸玩密室
4446: [Scoi2015]小凸玩密室
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 419 Solved: 173
[Submit][Status][Discuss]
Description
小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡。点亮所有灯
泡即可逃出密室。每个灯泡有个权值Ai,每条边也有个权值bi。点亮第1个灯泡不需要花费,之后每点亮4
个新的灯泡V的花费,等于上一个被点亮的灯泡U到这个点V的距离Du,v,乘以这个点的权值Av。在点灯
的过程中,要保证任意时刻所有被点亮的灯泡必须连通,在点亮一个灯泡后必须先点亮其子树所有灯泡才能点亮其他灯泡。请告诉他们,逃出密室的最少花费是多少。
Input
第1行包含1个数n,代表节点的个数
第2行包含n个数,代表每个节点的权值ai。(i=l,2,…,n)
第3行包含n-l个数,代表每条边的权值bi,第i号边是由第(i+1)/2号点连向第i+l号点的边。
(i=l,2...N-1)
Output
输出包含1个数,代表最少的花费。
Sample Input
3
5 1 2
2 1
5 1 2
2 1
Sample Output
5
HINT
对于100%的数据,1≤N≤2×105,1<Ai,Bi≤10^5
神题。
https://www.cnblogs.com/CXCXCXC/p/5312237.html
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define N 200010 4 using namespace std; 5 ll f[N][20],g[N][20]; 6 int n,v[N],w[N],dep[N],d[N]; 7 8 int main(){ 9 scanf("%d",&n);dep[1]=1; 10 for(int i=1;i<=n;i++) 11 scanf("%d",&v[i]); 12 for(int i=2;i<=n;i++){ 13 scanf("%d",&w[i]); 14 dep[i]=dep[i>>1]+1; 15 d[i]=d[i>>1]+w[i]; 16 } 17 for(int i=n;i;i--){ 18 if((i<<1)>n){ 19 for(int j=0;j<=dep[i];j++){ 20 int fa=i>>(dep[i]-j+1),to=(i>>(dep[i]-j))^1; 21 f[i][j]=1ll*(d[i]+d[to]-2*d[fa])*v[to]; 22 } 23 } 24 else if((i<<1)==n){ 25 for(int j=0;j<=dep[i];j++){ 26 int to=i<<1; 27 f[i][j]=f[to][j]+1ll*v[to]*w[to]; 28 } 29 } 30 else{ 31 int ls=i<<1,rs=ls|1; 32 for(int j=0;j<=dep[i];j++) 33 f[i][j]=min(1ll*v[ls]*w[ls]+f[ls][dep[ls]]+f[rs][j],1ll*v[rs]*w[rs]+f[rs][dep[rs]]+f[ls][j]); 34 } 35 } 36 for(int i=n;i;i--){ 37 if((i<<1)>n){ 38 for(int j=0;j<=dep[i];j++){ 39 int fa=i>>(dep[i]-j); 40 g[i][j]=1ll*(d[i]-d[fa])*v[fa]; 41 } 42 } 43 else if((i<<1)==n){ 44 int s=i<<1; 45 for(int j=0;j<=dep[i];j++) 46 g[i][j]=1ll*v[s]*w[s]+g[s][j]; 47 } 48 else{ 49 int ls=i<<1,rs=ls|1; 50 for(int j=0;j<=dep[i];j++) 51 g[i][j]=min(1ll*v[ls]*w[ls]+f[ls][dep[ls]]+g[rs][j],1ll*v[rs]*w[rs]+f[rs][dep[rs]]+g[ls][j]); 52 } 53 } 54 ll ans=g[1][0]; 55 for(int i=2;i<=n;i++){ 56 ll ret=g[i][dep[i]-1]; 57 for(int x=i;x>1;x>>=1){ 58 int y=x^1; 59 if(y>n)ret+=1ll*v[x>>2]*w[x>>1]; 60 else ret+=1ll*v[y]*w[y]+g[y][dep[y]-2]; 61 } 62 ans=min(ans,ret); 63 } 64 printf("%lld\n",ans); 65 return 0; 66 }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。