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

时间:2022-01-12 00:44:12

BZOJ

LOJ

洛谷


(下面点亮一个灯泡就说成染色了,感觉染色比较顺口...

注意完全二叉树\(\neq\)满二叉树,点亮第一个灯泡\(\neq\)第一次点亮一号灯泡,根节点应该就是\(1\)...

代价取决于下一次跳到哪个点,考虑记下这个状态,令\(f[i][j]\)表示染完\(i\)这棵子树后下一次染\(j\)的最小花费,但是状态数是\(O(n^2)\)的。

因为染色顺序很特殊,染完整棵\(i\)子树后下一步要么是染\(i\)的某个祖先,要么是染\(i\)的某个祖先的另一个儿子(除去\(i\)这棵子树外的另一棵子树)。同时树深是\(O(\log n)\)的,也就是一个点最多有\(\log n\)个祖先。

所以我们记\(f[i][j]\)表示染完\(i\)子树后,走到\(i\)的\(j\)级祖先的最小花费;\(g[i][j]\)表示染完\(i\)子树后,走到\(i\)的\(j\)级祖先的另一个儿子处(即\(i\)的\(j\)级祖先的兄弟节点)的最小花费。状态数是\(O(n\log n)\)的。

考虑\(f[i][j]/g[i][j]\)的转移。

如果\(i\)是叶子节点,那直接算一下走到对应节点的花费即可。

如果\(i\)只有左儿子,那走到左儿子再从左儿子走到对应节点即可。

否则\(i\)有两个儿子\(l,r\),要么是\(i\to l\to r\to i的对应祖先\),要么是\(i\to r\to l\to i的对应祖先\),取个\(\min\)即可。

DP的复杂度也是\(O(n\log n)\)的。

然后怎么统计以\(x\)作为起点的答案?

注意到一定是染完\(x\)子树,然后跳到\(fa[x]\),染\(fa[x]\)的另一棵子树(如果有);然后跳到\(fa[fa[x]]\),染\(fa[fa[x]]\)的另一棵子树...重复这个过程。

每次跳\(fa\),用DP数组统计一下花费就好了。总复杂度也是\(O(n\log n)\)。

注意是用dep[1]等于\(1\)来得到dep的(因为要算\(g[i][j]\),表示\(j\)级祖先的另一个儿子!)。


//72992kb	784ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define fa(x) (x>>1)
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define Anc(x,j) (x>>j)//x的j级祖先
#define Bro(x,j) ((x>>j-1)^1)//x的j级祖先的另一个儿子
typedef long long LL;
const int N=2e5+5,BIT=18; int A[N],dep[N],dis[N][BIT];
LL f[N][BIT],g[N][BIT];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
} int main()
{
const int n=read();
for(int i=1; i<=n; ++i) A[i]=read();
dep[1]=1;
for(int x=2; x<=n; ++x)
{
dep[x]=dep[fa(x)]+1, dis[x][1]=read();
for(int j=2; j<=dep[x]; ++j)
dis[x][j]=dis[fa(x)][j-1]+dis[x][1];
}
for(int x=n; x; --x)
{
int l=lson(x),r=rson(x);
for(int j=1; j<=dep[x]; ++j)
if(r<=n)
{
f[x][j]=std::min(1ll*A[l]*dis[l][1]+g[l][1]+f[r][j+1],1ll*A[r]*dis[r][1]+g[r][1]+f[l][j+1]);
g[x][j]=std::min(1ll*A[l]*dis[l][1]+g[l][1]+g[r][j+1],1ll*A[r]*dis[r][1]+g[r][1]+g[l][j+1]);
}
else if(l<=n)
{
f[x][j]=1ll*A[l]*dis[l][1]+f[l][j+1];
g[x][j]=1ll*A[l]*dis[l][1]+g[l][j+1];
}
else f[x][j]=1ll*dis[x][j]*A[Anc(x,j)], g[x][j]=1ll*(dis[x][j]+dis[Bro(x,j)][1])*A[Bro(x,j)];
}
LL ans=1ll<<61;
for(int i=1; i<=n; ++i)
{
LL now=f[i][1];
for(int x=fa(i),las=i; x; las=x,x=fa(x))
{
int y=las^1;
if(y<=n) now+=1ll*dis[y][1]*A[y]+f[y][2];
else now+=1ll*dis[x][1]*A[fa(x)];
}
ans=std::min(ans,now);
}
printf("%lld\n",ans); return 0;
}

BZOJ.4446.[SCOI2015]小凸玩密室(树形DP)的更多相关文章

  1. &lbrack;BZOJ4446&rsqb;SCoi2015 小凸玩密室 树形DP&lpar;烧脑高能预警&rpar;

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

  2. bzoj 4446&colon; &lbrack;Scoi2015&rsqb;小凸玩密室

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

  3. BZOJ4446&colon;&lbrack;SCOI2015&rsqb;小凸玩密室&lpar;树形DP&rpar;

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

  4. LUOGU P4253 &lbrack;SCOI2015&rsqb;小凸玩密室&lpar;树形dp&rpar;

    传送门 解题思路 玄学树形\(dp\),题目描述极其混乱...看错了两次题,设首先根据每次必须点完子树里的灯才能点别的,那么点灯情况只有两种,第一种是点到某一个祖先,第二种是点到某一个祖先的兄弟.所以 ...

  5. bzoj 4446&colon; &lbrack;Scoi2015&rsqb;小凸玩密室【树形dp】

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

  6. BZOJ 4443&colon; &lbrack;Scoi2015&rsqb;小凸玩矩阵 最大流

    4443: [Scoi2015]小凸玩矩阵 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Description 小凸和小方是好 ...

  7. bzoj 4443 &lbrack;Scoi2015&rsqb;小凸玩矩阵 网络流&comma;二分

    [Scoi2015]小凸玩矩阵 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1564  Solved: 734[Submit][Status][Di ...

  8. BZOJ4446 &lbrack;Scoi2015&rsqb;小凸玩密室 【树形Dp】

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

  9. &lbrack;bzoj4446&rsqb; &lbrack;loj&num;2009&rsqb; &lbrack;Scoi2015&rsqb; 小凸玩密室

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

随机推荐

  1. js基础篇——原型与原型链的详细理解

    js中的对象分为两种:普通对象object和函数对象function. function fn1(){}; var fn2 = function(){}; var fn3 = new Function ...

  2. 微软分布式云计算框架Orleans&lpar;2&rpar;:容灾与集群&lpar;1&rpar;

    在上一篇:微软分布式云计算框架Orleans(1):Hello World,我们大概了解了Orleans如何运用,当然上一篇的例子可以说是简单且无效的,因为用了Orleans不可能只写一个Hello ...

  3. DNS报文格式

    原文链接地址:http://blog.chinaunix.net/uid-24875436-id-3088461.html DNS报文格式(借个图贴过来):     说明一下:并不是所有DNS报文都有 ...

  4. 1099&period; Build A Binary Search Tree &lpar;30&rpar;

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  5. UVa 11300 Spreading the Wealth 分金币

    圆桌旁坐着 n 个人,每个人都有一定数量的金币,金币总数能够被 n 整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的金币数量的最小值,比如 n = 4, ...

  6. Spring框架

    Spring框架的根本使命是:简化JAVA开发,为了简化开发,有以下四个策略 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面和惯性进行声明式编程: 通过切面和模板 ...

  7. Feature Extractor&lbrack;SENet&rsqb;

    0.背景 这个模型是<Deep Learning高质量>群里的牛津大神Weidi Xie在介绍他们的VGG face2时候,看到对应的论文<VGGFace2: A dataset f ...

  8. effective c&plus;&plus; 笔记 &lpar;5-8&rpar;

    //---------------------------15/03/26---------------------------- //#5    了解c++默默编写并调用哪些函数 { /* c++会 ...

  9. Memcached命令:简单获取缓存value用法

    Memcached:命令用法1.cmd 输入telnet ip  端口 进入memcached服务端窗口比如:xxx.Token_T1435622096xxx为key获取此key的memcached ...

  10. 一些非常实用的JSON 教程

    以下内容来自W3school. JSON:JavaScript 对象表示法(JavaScript Object Notation). JSON 是存储和交换文本信息的语法.类似 XML. JSON 比 ...