第 2 次竞赛
A. 建树
--> 题目描述
请根据一棵树的后序和中序遍历顺序建树,并输出树的前序遍历顺序。
--> 输入格式
第一行有一个数字 $n$,表示节点的个数
第二行有 $n$ 个数字 $a_i$,表示树的后序遍历顺序
第三行有 $n$ 个数字 $b_i$,表示树的中序遍历顺序
--> 输出格式
$n$ 个数字,以空格隔开,表示树的前序遍历顺序。
--> 样例输入 #1
1 2 3 | |
--> 样例输出 #1
1 | |
解释
1 2 3 4 5 6树的结构如下所示 1 / \ 2 3 / 4
--> 样例输入 #2
1 2 3 | |
--> 样例输出 #2
1 | |
--> 样例输入 #3
1 2 3 | |
--> 样例输出 #1
1 | |
解释
1 2 3 4 5 6树的结构如下所示 1 / \ 2 3 / \ 4 5
--> 数据范围
- $1 \leq a_i \leq 10^5$,且 $a_i$ 互不相同。
- $1 \leq n \leq 10^4$
Solution
第 7 次竞赛 T2 (B. 树的左视角)要求根据前序序列 + 中序序列建树,根据这个模板修改即可(考场上你会发现“树的左视角”这题被锁定了,所以不能直接 copy,得自己提前准备)
| Solution | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
B. 翻转树
--> 题目描述
在一棵二叉树上有若干个节点,每个节点具有一个初始值 $a_i(-10^5 \leq a_i \leq 10^5,\;a_i \neq 0)$,现可对任意节点进行翻转操作:将当前节点及其所在子树所有节点的值均变为相反数。
问:最少经过多少次翻转操作,可使树上所有结点的值均为正?
--> 输入格式
第一行有一个数字 $n$,表示输入的长度
第二行有 $n$ 个数字 $a_i$,表示树的前序遍历过程中每个节点的初始值,空节点用 0 > 表示
--> 输出格式
输出一个整数,表示最少要进行的翻转次数。
--> 样例输入 #1
1 2 | |
--> 样例输出 #1
1 | |
解释>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18树的结构如下所示 -1 / \ 2 -3 / 4 第一次翻转-1节点所在子树,此时树变成了 1 / \ -2 3 / -4 第二次翻转-2节点所在子树,此时树变成了 1 / \ 2 3 / 4
--> 样例输入 #2
1 2 | |
--> 样例输出 #2
1 | |
解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32树的结构如下所示 1 / -2 / \ 3 4 \ 5 第一次翻转-2节点所在子树,此时树变成了 1 / 2 / \ -3 -4 \ -5 第二次翻转-3节点所在子树,此时树变成了 1 / 2 / \ 3 -4 \ 5 第三次翻转-4节点所在子树,此时树变成了 1 / 2 / \ 3 4 \ 5
--> 数据范围
- $-10^5 \leq a_i \leq 10^5, a_i \neq 0$。
- $1 \leq n \leq 2 \times 10^5$
Solution
需要意识到:
1- 问题可以自顶向下进行处理,因为每次反转操作对当前节点及其子树生效,不会再向上影响。因此遍历树采用前序遍历
2- 虽然每次翻转影响到子树的节点,导致子树的状态看上去不是很好维护,但是事实上反转操作可以看作 “零次 or 一次” 的循环,在前序遍历时传递一个 bool switch 就可以很好的维护子树状态
| Solution | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
C. 小蓝鲸组队
--> 题目背景
在一年一度的 C++ 创新杯中,许多聪明的小蓝鲸报名参赛。比赛允许自由组队,但每只小蓝鲸都提出了一些关于组队的愿望:
- 有些小蓝鲸彼此是好朋友,约定好一定要在同一队;
- 有些小蓝鲸性格不合,明确表示不想和对方在同一队。
现在,赛事组委会希望知道:是否存在一种分队方案,能够同时满足所有小蓝鲸的这些愿望?
--> 题目描述
给定 $n$ 条约束,每条形如:
- 小蓝鲸 $i$ 和 $j$ 约定好组队(记为 $e = 1$)
- 小蓝鲸 $i$ 和 $j$ 不想与对方组队(记为 $e = 0$)
判断是否存在一种分组方式,使得所有约束同时成立。
输入包含 $t$ 个独立的问题。对每个问题,若存在合法方案,输出 YES,否则输出 NO。
--> 输入格式
第一行包含一个正整数 $t$,表示需要判定的问题个数。
对于每个问题:
- 第一行包含一个正整数 $n$,表示该问题中的约束条件数量;
- 接下来 $n$ 行,每行包含三个整数 $i, j, e$,表示一条约束:
- 若 $e = 1$,表示小蓝鲸 $i$ 和 $j$ 必须在同一队;
- 若 $e = 0$,表示小蓝鲸 $i$ 和 $j$ 不能在同一队。
--> 输出格式
输出共 $t$ 行。 第 $k$ 行输出一个字符串 YES 或 NO(全部大写):
YES表示第 $k$ 个问题存在满足所有约束的分队方案;NO表示不存在。
--> 输入输出样例 #1
--> 输入
1 2 3 4 5 6 7 | |
--> 输出
1 2 | |
--> 输入输出样例 #2
--> 输入
1 2 3 4 5 6 7 8 9 10 | |
--> 输出
1 2 | |
--> 输入输出样例 #3
--> 输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
--> 输出
1 2 3 4 | |
--> 说明/提示
--> 样例解释
样例 1:
第一个问题中,要求 1 和 2 同队,又要求不同队,矛盾 →
NO。第二个问题中,两条约束均要求 1 和 2 同队,无冲突 →
YES。样例 2:
第一个问题:可全分到一队 →
YES。- 第二个问题:由 1,2,4 条可知 4 个小蓝鲸需要同队,但第 3 条要求 1 与 4 不同队,矛盾 →
NO。
--> 数据范围
- 对于 30% 的数据,$1 \le n \le 100$,$1 \le i, j \le 10^4$
- 对于 60% 的数据,$1 \le n \le 10^5$,$1 \le i, j \le 10^4$
- 对于 100% 的数据,$1 \le n \le 10^5$,$1 \le i, j \le 10^9$,$1 \le t \le 10$,$e \in {0,1}$
本题输入输出量较大,请使用高效的读写方式。
如果你使用 cin、cout 进行读写出现超时,可以考虑使用 scanf、 printf 或者在程序开头增加如下代码:
1 2 3 4 | |
时间复杂度过高的程序无论使用哪种读写方式都会超时。
Solution
利用并查集,先并后查
具体来说,先把必须为同一队伍的人进行合并,然后根据不能在同一队伍的约束情况进行合法性判断。如果合并操作后出现了 “两个不应该在同一组的人被分到同一组” 的情况,输出 NO,否则输出 YES
注意到数据范围 $1 \le i, j \le 10^9$ 不小,需要考虑离散化,或者用 unordered_map 存并查集(据说找个大质数用取模哈希也可以过)
| Solution | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |