[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 在踏得网开发过程中,我们在引导页面中 ...
随机推荐
- Ubuntu 把最小化、最大化和关闭按钮放到右边
1.按下"Ctrl+Alt+T"或者"ALT+F2"调出终端 2.输入"gconf-editor",回车.如果未安装gconf-editor ...
- Bootstrap -- 文本,背景,其他样式
Bootstrap -- 文本,背景,其他样式 1. 文本样式:展示了不同的文本颜色 使用文本样式: <!DOCTYPE html> <html> <head> & ...
- Linux之Samba部署
1.Samba介绍 Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的一个免费软件,由服务器及客户端程序构成,SMB(Server Messages Block,信息服务块)是一种 ...
- Java程序设计与数据结构导论--读后感
与我前面所读的<Java7基础教程>相比,此书不适合自学,更适合作为教材使用. 虽然此书完整覆盖了Java的知识点和数据结构的基础问题,并且对每个部分都做了基本说明.但是因为没有深入展开, ...
- insert into select的实际用法
INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table ...
- Jquery自动补全插件的使用
1.引入css和js <script src="js/jquery-ui.min.js"></script> <link href="cs ...
- 【English】20190326
Throughput吞吐量[ˈθruˌpʊt] data movement数据移动 [ˈdetə ˈmuvmənt] How to improve the Throughput for data ...
- .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]
原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...
- Autofs自动挂载探讨
Autofs介绍: mount是用来挂载文件系统的,可以在系统启动的时候挂载也可以在系统启动后挂载.对于本地固定设 备,如硬盘可以使用mount挂载:而光盘.软盘.NFS.SMB等文件系统具有动态性, ...
- Linux下禁止使用swap及防止OOM机制导致进程被kill掉
首先解释两个概念: swap:在linux里面,当物理内存不够用了,而又有新的程序请求分配内存,那么linux就会选择将其他程序暂时不用的数据交换到物理磁盘上(swap out),等程序要用的时候再读 ...