Description

小凸和小方相约玩密室逃脱,这个密室是一棵有 \(n\) 个节点的完全二叉树,每个节点有一个灯泡。点亮所有灯泡即可逃出密室。每个灯泡有个权值 \(Ai\) ,每条边也有个权值 \(bi\) 。点亮第 1 个灯泡不需要花费,之后每点亮 1 个新的灯泡 \(V\) 的花费,等于上一个被点亮的灯泡 \(U\) 到这个点 \(V\) 的距离 \(Du,v\),乘以这个点的权值 \(Av\) 。在点灯的过程中,要保证任意时刻所有被点亮的灯泡必须连通,在点亮一个灯泡后必须先点亮其子树所有灯泡才能点亮其他灯泡。

请告诉他们,逃出密室的最少花费是多少。

Input

第1行包含1个数 \(n\) ,代表节点的个数

第2行包含 \(n\) 个数,代表每个节点的权值 \(ai\) 。( \(i=1,2,…,n\) )

第3行包含 \(n-1\) 个数,代表每条边的权值 \(bi\) ,第 \(i\) 号边是由第 \((i+1)/2\) 号点连向第 \(i+1\) 号点的边。( \(i=l,2,...N-1\) )

Output

输出包含1个数,代表最少的花费。

Sample Input

3

5 1 2

2 1

Sample Output

5

HINT

对于 \(100\%\) 的数据,\(1 \leq N \leq 2 \times 10^5\),\(1<Ai,Bi \leq 10^5\)


想法

明显的树形 \(DP\) 。

但注意题中的2个坑点 !!!!!!

第一个点亮的节点不一定是1号点!

“完全二叉树”的意思的第 \(i\) 个点的父亲是 \(i/2\) ,但不保证所有非叶子节点都有两个孩子!

先假设第一个点亮的点是 1 。

那么树形 \(dp\) 的状态为:

\(dp[i][j]\) 表示当前 \(i\) 已被点亮,开始点亮以 \(i\) 为根的子树,将其全点亮后,最后一个点跑到 \(j\) 去点亮 \(j\) 的最少花费。

转移也挺显然的,考虑左右子哪个先点亮就行了,记忆化搜索。

由于在这种情况下,对每个 \(i\) ,有用的 \(dp[i][j]\) 中的 \(j\) 为其所有祖先的另一个孩子,不超过 \(O(logn)\) 个,所以总状态数 \(O(nlogn)\) ,不会超时。

交一发,\(WA\) 了。

于是开始换根。

对于先点亮的那个点,还是要先把它的子树点亮,然后再点亮它的父节点。

这时对每个 \(i\) ,有用的 \(dp[i][j]\) 中的 \(j\) 除了所有祖先的另一个孩子,还有它所有的祖先,但还是 \(O(logn)\) 级别,总复杂度 \(O(nlogn)\)。

记忆化搜索,然后超时了 \(qwq\)

那就不记忆化了(用 \(map\) 常数过大【捂脸】)

重新设状态——

\(f[i][j]\) 表示 \(dp[i][y]\) ,其中 \(y\) 为 \(i\) 的第 \(j+1\) 个祖先。

\(g[i][j]\) 表示 \(dp[i][z]\) ,其中 \(z\) 为 \(i\) 的第 \(j+1\) 个祖先的另一个孩子。

\(O(nlogn)\) 时间能把这些值都算出来,然后再换根。

交一发, \(WA\) 了。

发现不一定每个非叶子节点都有2个孩子,于是又改了改细节。终于 \(A\) 掉了!


代码

细节极多 【害怕】

#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;
}

[bzoj4446] [loj#2009] [Scoi2015] 小凸玩密室的更多相关文章

  1. [BZOJ4446]SCoi2015 小凸玩密室 树形DP(烧脑高能预警)

    4446: [Scoi2015]小凸玩密室 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点 ...

  2. BZOJ4446:[SCOI2015]小凸玩密室(树形DP)

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室. 每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...

  3. BZOJ4446 [Scoi2015]小凸玩密室 【树形Dp】

    题目 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 ...

  4. bzoj 4446: [Scoi2015]小凸玩密室

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...

  5. BZOJ4446 SCOI2015小凸玩密室(树形dp)

    设f[i][j]为由根进入遍历完i子树,最后一个到达的点是j时的最小代价,g[i][j]为由子树内任意一点开始遍历完i子树,最后一个到达的点是j时的最小代价,因为是一棵完全二叉树,状态数量是nlogn ...

  6. BZOJ4446: [Scoi2015]小凸玩密室

    用ui,j表示走完i的子树后走到i的深度为j的祖先的兄弟的最小代价: 用vi,j表示走完i的子树后走到i的深度为j的祖先的最小代价,用u算出v. 枚举起点,计算答案. #include<bits ...

  7. 2019.03.26 bzoj4446: [Scoi2015]小凸玩密室(树形dp)

    传送门 题意简述: 给一棵完全二叉树,有点权aia_iai​和边权,每个点有一盏灯,现在要按一定要求点亮: 任意时刻点亮的灯泡必须连通 点亮一个灯泡后必须先点亮其子树 费用计算如下:点第一盏灯不要花费 ...

  8. BZOJ.4446.[SCOI2015]小凸玩密室(树形DP)

    BZOJ LOJ 洛谷 (下面点亮一个灯泡就说成染色了,感觉染色比较顺口... 注意完全二叉树\(\neq\)满二叉树,点亮第一个灯泡\(\neq\)第一次点亮一号灯泡,根节点应该就是\(1\)... ...

  9. bzoj 4446: [Scoi2015]小凸玩密室【树形dp】

    神仙题!参考https://www.cnblogs.com/wfj2048/p/7695711.html 注意完全二叉树不是满二叉树!!!! 设g[u][j]为u遍历完子树到深度为i-1的祖先的兄弟的 ...

随机推荐

  1. Makefile记录

    需要把sum.c编译汇编成可执行程序zzj zzj:sum.o gcc -o zzj sum.osum.o:sum.c gcc -c -o sum.o sum.cclean: rm -rf *.o z ...

  2. [板子]SPFA算法+链式前向星实现最短路及负权最短路

    参考:https://blog.csdn.net/xunalove/article/details/70045815 有关SPFA的介绍就掠过了吧,不是很赞同一些博主说是国内某人最先提出来,Bellm ...

  3. Keras mlp 手写数字识别示例

    #基于mnist数据集的手写数字识别 #构造了三层全连接层组成的多层感知机,最后一层为输出层 #基于Keras 2.1.1 Tensorflow 1.4.0 代码: import keras from ...

  4. JavaScript模块化演变 CommonJs,AMD, CMD, UMD(一)

    原文链接:https://www.jianshu.com/p/33d53cce8237 原文系列2链接:https://www.jianshu.com/p/ad427d8879cb 前端完全手册: h ...

  5. 21.python的模块(Module)和包(Package)

    目录 模块(Module)和包(Package) 模块(modue)的概念 模块导入方法 1.import 语句 2.from-import 语句 3.from-import* 语句 4.运行本质 i ...

  6. PRML第一章读书小结

    PRML第一章读书小结     第一章用例子出发,较为简单的引入了概率论.模型.决策.损失.信息论的问题,作为机器学习从业者,读PRML除了巩固已有基础,还受到了很多新的启发,下面将我收到的启发总结如 ...

  7. 【题解】P3645 [APIO2015]雅加达的摩天楼(分层图最短路)

    [题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是\(O(n^2)\)的过不去 然而我们有一个优化的办法,可以建一个新图\(G=( ...

  8. $HDU$ 4336 $Card\ Collector$ 概率$dp$/$Min-Max$容斥

    正解:期望 解题报告: 传送门! 先放下题意,,,已知有总共有$n$张卡片,每次有$p_i$的概率抽到第$i$张卡,求买所有卡的期望次数 $umm$看到期望自然而然想$dp$? 再一看,哇,$n\le ...

  9. Spring 资源注入

    Spring开发中经常需要调用各种资源,包含普通文件.网址.配置文件.系统环境变量等,我们可以使用Spring表达式语言(Spring-EL)实现资源的注入. Spring主要使用@Value注解实现 ...

  10. 「Luogu P2015」二叉苹果树 解题报告

    题面 一个二叉树,边数为n\((2<n\le 100)\),每条边有一个权值,求剪枝后剩下p\((1<p<n)\)条边,使p条边的权值和最大 还看不懂?-- 2 5 input:5 ...