bzoj4446[Scoi2015]小凸玩密室

4446: [Scoi2015]小凸玩密室

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

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 }

 

posted @ 2018-01-21 16:59  _wsy  阅读(325)  评论(0编辑  收藏  举报