洛谷 P6776 - [NOI2020] 超现实树(找性质,神仙题)
nb tea 一道!
首先考虑怎样入手分析这个看似非常不可做的问题。首先题目涉及高度无穷的树,根本枚举不了。不过我们冷静一下就会发现,如果我们记 \(mx=\max\limits_{i=1}^{n}\text{dep}(T_i)\),那么由于初始树的集合中不存在深度 \(>mx\) 的树,因此所有可以生成的深度 \(>mx\) 的树都经过了生长操作,也是说:
Observation \(1\). 对于某个深度 \(d>mx\),存在深度为 \(d\) 的树不能通过生长得到的充要条件是存在深度为 \(d-1\) 的树不能通过生长得到。
证明大概就反证一下?假设深度为 \(d-1\) 的树都能生长得到,那么对于一棵深度为 \(d\) 的树显然可以通过砍掉它所有叶子得到的深度为 \(d-1\) 的树生长得到。而对于一棵不能生长得到的深度为 \(d-1\) 的树,将它深度为 \(d-1\) 的叶子向下延伸一格,得到的深度为 \(d\) 的树也无法通过生长操作得到,又 \(d>mx\),因此得到的深度为 \(d\) 的树也不在初始的树集合中,也无法得到。
因此我们只用检验是否存在深度为 \(mx\) 的树不能通过生长操作得到即可。
那么我们是否究竟需要把所有深度为 \(mx\) 的树都检验一遍呢?
Observation \(2\). 所有深度为 \(mx\) 的树都能够通过生长操作得到,等价于所有深度为 \(mx\) 的链树(caterpillar)都能够通过生长操作得到,其中链树的定义是,存在一条根节点到某个叶子节点的路径,满足其它点到这条路径的距离都 \(\le 1\)。
显然如果所有链树都能够通过生长操作得到,那么对于一棵深度为 \(mx\) 的树,我们找出根节点到其任意一个深度为 \(mx\) 的叶子的路径,然后对于路径上每个点 \(p_i\),我们找出它不在这条路径上的儿子(显然这个儿子是唯一的),如果存在我们就把它的子树缩成一个点,那么这个树就可以由缩得的这个链树生长得到。而如果存在某个链树无法通过生长得到,那……显然由于链树 \(\in\) 树,必然存在某个深度为 \(mx\) 的树无法通过生长得到。
Observation \(3\). 非链树无法生成链树
显然,由于生长操作不支持删点,因此如果存在某个点,满足其左右儿子子树大小较小值 \(>1\),那该节点不论怎么生长,其左右儿子子树大小较小值永远 \(>1\)。
Observation \(4\). 对于输入中的树的集合,我们只用保留其中是链树的树
由于非链树不能生成链树,所以我们保留它们也没有用。
Observation \(5\). 一棵深度为 \(d\) 的链树可以压缩成一个长度为 \(d\) 的四进制树
对于一棵深度为 \(d\) 的链树 \(T\),考虑其主链 \(C\),那么对于主链上任意一个点 \(p_i\),有四种可能:
- \(p_i\) 的左儿子在链树主链上,\(p_i\) 没有右儿子
- \(p_i\) 的右儿子在链树主链上,\(p_i\) 没有左儿子
- \(p_i\) 的左儿子在链树主链上,\(p_i\) 右儿子为叶子节点
- \(p_i\) 的右儿子在链树主链上,\(p_i\) 左儿子为叶子节点
注意,对于链树主链上倒数第二个节点,如果它的两个儿子都是叶子节点,此时该链树就有两个叶子节点,此时也就对应有两种压缩方法。
那么我们的任务即为查看是否所有这样长度为 \(mx\) 的四进制数都能够通过某种方式得到。
我们考虑对于一棵链树,按照如下方式将其压缩成一个或两个四进制数并将其对应到一个四叉树上,那么四叉树上的某个节点,如果其子树中只有有限棵树无法被生成,那么必定有:
- 该点在某一棵链树中为叶子节点,此时它可以替换为任何四进制数。
- 该点拥有全部四个儿子,且四个儿子代表的子树中都仅有有限棵树无法被生成。
否则如果它儿子个数 \(<4\),并且它不在任何一棵链树中是叶子节点,那么它缺失的儿子对应的链树就无法被表示出来。
按照如上方式建出四叉树,然后对四叉树进行一遍 DFS 即可求出答案。
时间复杂度 \(\mathcal O(n)\)
希望今年 NOI D2 不要出这么阴间的题(
不过话说回来今年 D1 这么良心估计 D2 得做好被虐的准备了/qiao
const int MAXN=2e6;
int ch[MAXN+5][2],ch_[MAXN+5][4],siz[MAXN+5],ncnt,rt,ok[MAXN+5];
bool checkchain(int x){
siz[x]=1;
for(int i=0;i<2;i++) if(ch[x][i]){
if(!checkchain(ch[x][i])) return 0;
siz[x]+=siz[ch[x][i]];
} return !(ch[x][0]&&ch[x][1]&&min(siz[ch[x][0]],siz[ch[x][1]])>1);
}
void insert(int &x,int y){
if(!x) x=++ncnt;
// printf("%d %d\n",x,y);
if(!ch[y][0]&&!ch[y][1]) return ok[x]=1,void();
if(ch[y][0]&&!ch[y][1]) return insert(ch_[x][0],ch[y][0]),void();
if(!ch[y][0]&&ch[y][1]) return insert(ch_[x][1],ch[y][1]),void();
if(siz[ch[y][0]]==1) insert(ch_[x][2],ch[y][1]);
if(siz[ch[y][1]]==1) insert(ch_[x][3],ch[y][0]);
}
bool dfs(int x){
if(ok[x]) return 1;if(!x) return 0;ok[x]=1;
for(int i=0;i<4;i++) ok[x]&=dfs(ch_[x][i]);return ok[x];
}
void solve(){
int N;scanf("%d",&N);ncnt=rt=0;
memset(ch_,0,sizeof(ch_));memset(ok,0,sizeof(ok));
while(N--){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&ch[i][0],&ch[i][1]);
if(!checkchain(1)) continue;insert(rt,1);
} printf("%s\n",dfs(rt)?"Almost Complete":"No");
}
int main(){
// freopen("surreal.in","r",stdin);freopen("surreal.out","w",stdout);
int qu;scanf("%d",&qu);while(qu--) solve();
return 0;
}
洛谷 P6776 - [NOI2020] 超现实树(找性质,神仙题)的更多相关文章
- Solution -「NOI 2020」「洛谷 P6776」超现实树
\(\mathcal{Description}\) Link. 对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...
- 【BZOJ2830/洛谷3830】随机树(动态规划)
[BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- 洛谷P3655 差分数组 树状数组
题目链接:https://www.luogu.org/problemnew/show/P3655 不一定对,仅供参考,不喜勿喷,不喜勿喷. 先copy洛谷P3368 [模板]树状数组 2 题解里面一位 ...
- 洛谷:P1087 FBI树 P1030 求先序排列 P1305 新二叉树
至于为啥把这三个题放到一起,大概是因为洛谷的试炼场吧,三道树的水题,首先要理解 先序中序后序遍历方法. fbi树由于数量小,在递归每个区间时,暴力跑一遍区间里的数,看看是否有0和1.至于递归的方法,二 ...
- 【洛谷 5002】专心OI - 找祖先 (树上计数)
专心OI - 找祖先 题目背景 \(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来. 题目描述 这个游戏会给出你一棵树,这 ...
- Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
随机推荐
- 【UE4 设计模式】建造者模式 Builder Pattern
概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...
- Java多线程中的死锁
Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...
- 通过简单例子 | 快速理清 UML 中类与类的六大关系
关于封面:我想我们都会离开 类与类之间的六大关系 泛化 ( Generalization ) ---> 表继承关系 实现 ( Realization ) 关联 ( Association ) 聚 ...
- LeetCode:回溯算法
回溯算法 这部分主要是学习了 labuladong 公众号中对于回溯算法的讲解 刷了些 leetcode 题,在此做一些记录,不然没几天就忘光光了 总结 概述 回溯是 DFS 中的一种技巧.回溯法采用 ...
- [no_code][Beta]事后分析
设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的目前的手写表单的电子化问题,办公电子化问题的一个key问题.定义十分清楚: 输入: 手写表单 ...
- 技术博客--微信小程序canvas实现图片编辑
技术博客--微信小程序canvas实现图片编辑 我们的这个小程序不仅仅是想给用户提供一个保存和查找的平台,还希望能给用户一个展示自己创意的舞台,因此我们实现了图片的编辑部分.我们对对图片的编辑集成了很 ...
- Flink入门-第一篇:Flink基础概念以及竞品对比
Flink入门-第一篇:Flink基础概念以及竞品对比 Flink介绍 截止2021年10月Flink最新的稳定版本已经发展到1.14.0 Flink起源于一个名为Stratosphere的研究项目主 ...
- springcloud3(六) 服务降级限流熔断组件Resilience4j
代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-gateway/src/test/java/com/ ...
- prometheus(7)之数据类型与PromQL语法
Prometheus的四种数据类型 counter (只增不减 计数) Gauge (常规数值 可变化大小) histogram (柱状图 小于上边界的 总数与次数) summary (分位数 小于 ...
- windows端口占用处理方法
(1)输入命令:netstat -ano,列出所有端口的情况.在列表中我们观察被占用的端口,比如是8081,首先找到它.C:\Users\Administrator>netstat -ano活动 ...