[BZOJ4446]SCoi2015 小凸玩密室 树形DP(烧脑高能预警)
4446: [Scoi2015]小凸玩密室
Time Limit: 10 Sec Memory Limit: 128 MB
Description
Input
Output
Sample Input
5 1 2
2 1
Sample Output
HINT
对于100%的数据,1≤N≤2×105,1<Ai,Bi≤10^5
(其实我是回来补暑假没写完的题解的)
题解:
(首先我经过激烈的思想斗争,认为那个点亮灯泡的花费计算只与上一个有关(其实是因为前4个太难考虑了...)
事实证明这样做是对的..就是只考虑上一个:(
有了之前做非线性DP的经验,我一开始想的还是合并类型
但是发现数据范围不太对....这似乎是一个介于O(n)和O(n2)范围内的DP
我们考虑怎么定义状态,以及怎么转移.
一开始我想的是f[i][j]表示"走完以i为根的子树之后走去j点的最小花费"
但是我发现这个MLE了,2e5开不下
但是这又是一颗完全二叉树,所以我们考虑能不能应用他的一些性质
我们观察到,点灯泡的起点没有确定,但是题目有这样的两个限制:
要保证任意时刻所有被点亮的灯泡必须连通.
在点亮一个灯泡后必须先点亮其子树所有灯泡才能点亮其他灯泡
这样的话,某一个点被点亮的时候只能有三种转移的情况:从儿子走来,从兄弟走来和从父亲走来(废话)
因此,当某一个子树被完全点亮之后,我们就要去某一个他的祖先,或者是他某个祖先的儿子
我们发现上面这两个都与这个节点的祖先有关(这里我们把自己也看成自己的祖先)
由于这是一棵二叉树,我们完全可以通过位运算(左移,右移和异或)来计算出某个节点的某个深度的祖先.
这样,第二维完全不用是O(n)的:我们可以把第二维设为深度,即走完以i为根的子树之后走去深度为j的祖先节点的“XXXX”的最小花费
那么我们再考虑一下:我们这个点的祖先节点可能已经被点亮,也可能没有被点亮。如果已经点亮,我们就必须去点亮祖先的兄弟那棵子树。
因此我们定义两个数组:
f(ather)[i][j]表示走完以i为根的子树之后去点亮深度为j的祖先节点的最小花费
b(rother)[i][j]表示走完以i为根的子树之后去点亮深度为j的祖先节点的兄弟节点的最小花费
接下来我们考虑状态的转移。最好想到的是节点i是叶子节点的情况:直接走去对应的节点即可。
完整代码见下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=;
typedef long long LL;
int n,l[N],r[N],deep[N];
LL f[N][],b[N][],a[N],lval[N],rval[N],dis[N];
int main()
{
scanf("%d",&n);LL v;int rt;deep[]=;
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
for(int i=;i<n;i++)
{
scanf("%lld",&v);
rt=(i+)>>,deep[i+]=deep[rt]+;
if((i+)&) r[rt]=i+,rval[rt]=v,dis[r[rt]]=dis[rt]+rval[rt];
else l[rt]=i+,lval[rt]=v,dis[l[rt]]=dis[rt]+lval[rt];
}
for(int i=n;i>;i--)
for(int j=;j<=deep[i];j++)
if(!r[i])
if(!l[i])
{
int fa=i>>(deep[i]-j+),fab=(i>>(deep[i]-j))^;
b[i][j]=( dis[i]+dis[fab]-(dis[fa]<<) )*a[fab];
}
else b[i][j]=lval[i]*a[l[i]]+b[l[i]][j];
else b[i][j]=min(lval[i]*a[l[i]]+b[l[i]][deep[i]+]+b[r[i]][j],rval[i]*a[r[i]]+b[r[i]][deep[i]+]+b[l[i]][j]);
for(int i=n;i;i--)
for(int j=;j<=deep[i];j++)
{
if(!r[i])
if(!l[i])
if(!j)f[i][j]=;
else
{
int fa=i>>(deep[i]-j);
f[i][j]=(dis[i]-dis[fa])*a[fa];
}
else f[i][j]=lval[i]*a[l[i]]+f[l[i]][j];
else f[i][j]=min(lval[i]*a[l[i]]+b[l[i]][deep[i]+]+f[r[i]][j],rval[i]*a[r[i]]+b[r[i]][deep[i]+]+f[l[i]][j]);
}
LL ans=f[][];
for(int i=;i<=n;i++)
{
int u=i,bro=u^;
LL tmp=f[u][deep[u]-];
while(u>)
{
if(bro>n)tmp+=a[u>>]*(dis[u>>]-dis[u>>]);
else tmp+=a[bro]*(dis[bro]-dis[u>>])+f[bro][deep[u>>]-];
u>>=,bro=u^;
}
ans=min(ans,tmp);
}
printf("%lld\n",ans);
}
[BZOJ4446]SCoi2015 小凸玩密室 树形DP(烧脑高能预警)的更多相关文章
- BZOJ4446:[SCOI2015]小凸玩密室(树形DP)
Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室. 每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...
- LUOGU P4253 [SCOI2015]小凸玩密室(树形dp)
传送门 解题思路 玄学树形\(dp\),题目描述极其混乱...看错了两次题,设首先根据每次必须点完子树里的灯才能点别的,那么点灯情况只有两种,第一种是点到某一个祖先,第二种是点到某一个祖先的兄弟.所以 ...
- BZOJ.4446.[SCOI2015]小凸玩密室(树形DP)
BZOJ LOJ 洛谷 (下面点亮一个灯泡就说成染色了,感觉染色比较顺口... 注意完全二叉树\(\neq\)满二叉树,点亮第一个灯泡\(\neq\)第一次点亮一号灯泡,根节点应该就是\(1\)... ...
- BZOJ4446 [Scoi2015]小凸玩密室 【树形Dp】
题目 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 ...
- 2019.03.26 bzoj4446: [Scoi2015]小凸玩密室(树形dp)
传送门 题意简述: 给一棵完全二叉树,有点权aia_iai和边权,每个点有一盏灯,现在要按一定要求点亮: 任意时刻点亮的灯泡必须连通 点亮一个灯泡后必须先点亮其子树 费用计算如下:点第一盏灯不要花费 ...
- BZOJ4446 SCOI2015小凸玩密室(树形dp)
设f[i][j]为由根进入遍历完i子树,最后一个到达的点是j时的最小代价,g[i][j]为由子树内任意一点开始遍历完i子树,最后一个到达的点是j时的最小代价,因为是一棵完全二叉树,状态数量是nlogn ...
- BZOJ4446: [Scoi2015]小凸玩密室
用ui,j表示走完i的子树后走到i的深度为j的祖先的兄弟的最小代价: 用vi,j表示走完i的子树后走到i的深度为j的祖先的最小代价,用u算出v. 枚举起点,计算答案. #include<bits ...
- [bzoj4446] [loj#2009] [Scoi2015] 小凸玩密室
Description 小凸和小方相约玩密室逃脱,这个密室是一棵有 \(n\) 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 \(Ai\) ,每条边也有个权值 \ ...
- bzoj 4446: [Scoi2015]小凸玩密室
Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...
随机推荐
- 初学者浅谈我对领域驱动设计(DDD)的理解
一.为什么要学习领域驱动设计 如果你已经设计出了优雅而万能的软件架构,如果你只是想做一名高效的编码程序员,如果你负责的软件并不复杂,那你确实不需要学习领域驱动设计. 如果用领域驱动设计带来的收获: 能 ...
- sqlite导入mysql
在线阅读地址 http://wenku.baidu.com/view/cc6821a8482fb4daa58d4bb8
- CentOS7.2下配置SOCKS5代理
SOCKS介绍: 1.这里只做简单介绍. SOCKS5 是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Int ...
- RobotFramework测试环境搭建记录
Robotframwork测试环境搭建记录 1.安装Python2.7(https://www.python.org/) 在环境变量path中加入“C:\Python27” 安装后的验证方法为在命令行 ...
- ThinkPHP3.2开发仿京东商城项目实战视频教程
ThinkPHP3.2仿京东商城视频教程实战课程,ThinkPHP3.2开发大型商城项目实战视频 第一天 1.项目说明 2.时间插件.XSS过滤.在线编辑器使用 3.商品的删除 4.商品的修改完成-一 ...
- Linux AD 身份统一验证(SSO)
http://www.toxingwang.com/linux-unix/linux-admin/584.html Linux+samba-winbind+AD实现统一认证 2013年04月27日 ⁄ ...
- github在版本库中删除某个文件的所有历史记录
github的目的就是版本控制,记录每一个版本的变动.然而有的时候我们往往希望从版本库中彻底删除某个文件,不再显示在历史记录中.例如不小心上传了一堆错误的文件,或者不小心上传了帐号.密码,那么这个时候 ...
- Django_csrf
CSRF攻击介绍 CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作.比如说,受害者 Bob 在银行有一笔存款,通过对银行的 ...
- 作业1-MathExam
MathExam 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 10 30 • Estim ...
- Tomcat提高并发
Centos7环境下Tomcat 启动慢的解决方案1.增加熵值(本质增加random)安装软件 >> Yum –y install rng-tools 启动熵服务 >> Sys ...