[APIO2007] 风铃
题目链接
可能是个树上 DP?指针真好玩 23333。
首先对于所有玩具如果有深度差超过 1 的就是无解(在这里贡献 WA * 3),所以 dfs 一遍记录深度是有必要的……
然后如果有一个点的两颗子树中都含有最小、最大深度,那么这种情况也是无解,可以令同时含有两种深度的子树 tag = 1。
然后考虑最少交换次数,对于每一个节点的左右子树,三种情况需要交换:
1. 左边全是小深度的,右边全是大深度的
2. 左边全是小深度的,右边大小深度都有
3. 左边大小深度都有,右边全是大深度的
root->cnt = left_child->cnt + right_child->cnt + 本次是否需要交换(0 or 1)。
所以代码判的挺多的……
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = + ;
int n, in_deg[maxn], maxx, minn, ans, node_num; struct Node {
int deep, cnt, tag, type;
Node *lchild, *rchild; Node() { type = cnt = deep = , lchild = rchild = NULL; }
~Node() {};
} node[maxn], *p_root; inline int read() {
register char ch = ; register int w = , x = ;
while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar();
while( isdigit(ch) ) x = (x * ) + (ch ^ ), ch = getchar();
return w ? -x : x;
} inline void Set_deep(Node *x) {
if( x->lchild != NULL ) x->lchild->deep = x->deep + , Set_deep(x->lchild);
if( x->rchild != NULL ) x->rchild->deep = x->deep + , Set_deep(x->rchild);
} inline void Deep_fs(Node *x) {
if( x->lchild == NULL && x->rchild == NULL ) return ;
if( x->lchild != NULL ) Deep_fs(x->lchild);
if( x->rchild != NULL ) Deep_fs(x->rchild);
if( x->lchild->tag && x->rchild->tag ) ans = -;
if( x->lchild->type ^ x->rchild->type ) x->tag = ;
else if( x->lchild->tag | x->rchild->tag ) x->tag = ;
else if( x->lchild->deep != x->rchild->deep ) x->tag = ;
x->cnt = x->lchild->cnt + x->rchild->cnt;
x->deep = max(x->lchild->deep, x->rchild->deep);
if( x->lchild->tag ^ x->rchild->tag ) {
if( x->lchild->tag && x->lchild->deep == x->rchild->deep ) ++x->cnt;
if( x->rchild->tag && x->lchild->deep < x->rchild->deep ) ++x->cnt;
} else if( x->lchild->deep < x->rchild->deep ) ++x->cnt;
} int main(int argc, const char *argv[])
{
freopen("..\\nanjolno.in", "r", stdin);
freopen("..\\nanjolno.out", "w", stdout); scanf("%d", &n), node_num = n, minn = 2e9;
for(int l, r, i = ; i <= n; ++i) {
l = read(), r = read();
if( l == - ) node[++node_num].type = , node[i].lchild = &node[node_num];
else node[i].lchild = &node[l], ++in_deg[l];
if( r == - ) node[++node_num].type = , node[i].rchild = &node[node_num];
else node[i].rchild = &node[r], ++in_deg[r];
}
for(int i = ; i <= n; ++i) if( in_deg[i] == ) p_root = &node[i];
p_root->deep = , Set_deep(p_root);
for(int i = ; i <= node_num; ++i) if( node[i].type ) {
maxx = max(maxx, node[i].deep), minn = min(minn, node[i].deep);
}
if( maxx - minn > ) puts("-1");
else Deep_fs(p_root), printf("%d\n", ans == - ? ans : p_root->cnt); fclose(stdin), fclose(stdout);
return ;
}
—— “从你慷慨的手里所付予的,我都接受。我别无所求。”
“是了,是了,我懂得你,谦卑的乞丐,你是乞求一个人的一切所有。”
[APIO2007] 风铃的更多相关文章
- [APIO2007]风铃 --- 贪心
[APIO2007]风铃 题目描述 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品, ...
- 题解:[APIO2007]风铃
你需要选一个满足下面两个条件的风铃:(1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层.(2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点. ...
- BZOJ1149:[CTSC/APIO2007]风铃——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1149 https://www.luogu.org/problemnew/show/P3621 sb ...
- [洛谷P3621] [APIO2007] 风铃
Description 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品,一般挂在天花 ...
- 洛谷 P3621 [APIO2007]风铃【贪心】
没有算法,但是要注意细节. 首先无解的情况,显然的是最小深度的叶子节点和最大深度的叶子节点的深度差大于1:还有一种比较难想,就是如果一个点的左右子树都有最大和最小深度的叶子节点,这样交换左右子树也不行 ...
- LuoguP3621 [APIO2007]风铃
https://zybuluo.com/ysner/note/1140124 题面 题面复杂,戳我 解析 看着这道题... 似乎与[HNOI/AHOI2018]道路有不可言妙的相似之处. (题面吓人, ...
- dp式子100个……
1. 资源问题1-----机器分配问题F[I,j]:=max(f[i-1,k]+w[i,j-k]) 2. 资源问题2------01背包问题F[I,j]:=max(f[i- ...
- dp方程
1. 资源问题1 -----机器分配问题 F[I,j]:=max(f[i-1,k]+w[i,j-k]) 2. 资源问题2 ------01背包问题 F[I,j]:=ma ...
- 基于Kinetic框架实现超酷的风铃悬挂摆动效果
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/iefreer/article/details/37049987 在踏得网开发过程中,我们在引导页面中 ...
随机推荐
- Linux内存描述之高端内存--Linux内存管理(五)
1. 内核空间和用户空间 过去,CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间, ...
- c/c++ 多线程 利用条件变量实现线程安全的队列
多线程 利用条件变量实现线程安全的队列 背景:标准STL库的队列queue是线程不安全的. 利用条件变量(Condition variable)简单实现一个线程安全的队列. 代码: #include ...
- Linux shell 及命令汇总
1 文件管理命令 1.cat命令:将文件内容连接后传送到标准输出或重定向到文件 2.chmod命令:更改文件的访问权限 3.chown命令:更改文件的所有者 4.find命令:查找(符合条件)文件并将 ...
- Linux、CentOS7下JDK环境配置
Linux版本 1.上传JDK包至指定目录,并解压 tar -xzvf jdk-7u80-linux-x64.tar.gz 2.配置JDK环境变量 打开/etc/profile配置文件 vim /et ...
- 个人对JS原型链的一些理解(prototype、__proto__)
前言 在我一开始学习java web的时候,对JS就一直抱着一种只是简单用用的心态,于是并没有一步一步地去学习,当时认为用法与java类似,但是在实际web项目中使用时却比较麻烦,便直接粗略了解后开始 ...
- JS中的闭包(closure)
JS中的闭包(closure) 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面就是我的学习笔记,对于Javascript初学者应该是很有用 ...
- slice()和splice()区别
1.slice(start,end):方法可从已有数组中返回选定的元素,返回一个新数组,包含从start到end(不包含该元素)的数组元素. 注意:该方法不会改变原数组,而是返回一个子数组,如果想删除 ...
- 如何给python程序加密
在实际的工作中,有时候我们需要部署自己的Python应用,但这时候我们并不希望别人能够看到自己的Python源程序.因此,我们需要为自己的源代码进行加密,Python已经为我们提供了这样一套工作机制. ...
- 013_实践HTTP206状态:部分内容和范围请求
HTTP 2xx范围内的状态码表明了:"客户端发送的请求已经被服务器接受并且被成功处理了".HTTP/1.1 200 OK是HTTP请求成功后的标准响应,当你在浏览器中打开www. ...
- 26 python 初学(线程、同步锁、死锁和递归锁)
参考博客: www.cnblogs.com/yuanchenqi/articles/5733873.html 并发:一段时间内做一些事情 并行:同时做多件事情 线程是操作系统能够进行运算调度的基本单位 ...