#44. 还有人类吗
还有人类吗
还有人类吗
题目描述
某天晚上,机房里正在进行一场 AtCoder Beginner Contest。
比赛开始后不久,一位 VJudge 标识末尾两字符经 Base64 编码后为 aHQ= 的选手,仿佛成功建立了通向题解空间的秘密信道,连续通过前六道题,排名一度冲到了 rk 40。
小 R 老师盯着排行榜沉默良久,终于忍不住对这位选手说了一句话:
感觉你已经不是人类了。
据说这位选手平日里极其擅长数据结构。为了检验他的数据结构能力究竟属于人类范畴,还是来自某种黑盒预言机的加密通信,小 R 老师决定拿出一道关于二叉搜索树的题。
一棵二叉搜索树是一棵有根二叉树,每个节点上有一个权值。对于任意节点 ,若它的权值为 ,则:
- 左子树内所有节点的权值都小于 ;
- 右子树内所有节点的权值都大于 。
我们用如下过程描述在一棵 BST 中查找权值 :
void find(x, a) {
if (x == 0 || w[x] == a) return;
if (w[x] > a) find(l[x], a);
else find(r[x], a);
}
其中 表示空节点, 和 分别表示 的左儿子和右儿子。
定义 为执行 find(root, a) 时访问到的所有非空节点组成的序列。
定义这次查找的代价为:
现在有 棵初始为空的 BST,编号为 。
接下来有 次操作,操作分为两种:
1 l r w:对于所有 ,将整数 插入第 棵 BST 中。插入从根开始,按照和find(root, w)相同的方式向下走;如果走到空节点,则在该位置新建一个权值为 的节点。2 x a:求在第 棵 BST 中查找 的代价。
题目保证所有第一类操作中的 两两不同。
输入格式
第一行包含两个整数 ,分别表示 BST 的数量和操作次数。
接下来 行,每行描述一次操作,格式为以下两种之一:
1 l r w
或
2 x a
含义如题目描述所示。
输出格式
对于每个第二类操作,输出一行一个整数,表示对应查找的代价。
样例输入
3 9
1 1 2 2
1 1 3 1
1 2 3 3
2 1 2
2 1 4
2 2 2
2 2 4
2 3 2
2 3 4
样例输出
2
2
2
5
4
4
样例解释
前三次操作后:
第 棵 BST 中依次插入了 ,其结构为:
2
/
1
因此查找 的代价为 ,查找 时只访问节点 ,代价也为 。
第 棵 BST 中依次插入了 ,其结构为:
2
/ \
1 3
因此查找 的代价为 ,查找 时访问节点 ,代价为:
第 棵 BST 中依次插入了 ,其结构为:
1
\
3
因此查找 和 时都会访问节点 ,代价均为:
样例 2
见选手目录下的 human/human2.in 与 human/human2.ans。
该样例满足测试点 的约束条件。
样例 3
见选手目录下的 human/human3.in 与 human/human3.ans。
该样例满足测试点 的约束条件。
样例 4
见选手目录下的 human/human4.in 与 human/human4.ans。
该样例满足测试点 的约束条件。
样例 5
见选手目录下的 human/human5.in 与 human/human5.ans。
该样例满足测试点 的约束条件。
样例 6
见选手目录下的 human/human6.in 与 human/human6.ans。
该样例满足测试点 的约束条件。
样例 7
见选手目录下的 human/human7.in 与 human/human7.ans。
该样例满足测试点 的约束条件。
样例 8
见选手目录下的 human/human8.in 与 human/human8.ans。
该样例满足测试点 的约束条件。
数据范围
对于所有测试数据,均满足:
- ;
- 对于第一类操作,,;
- 对于第二类操作,,;
- 所有第一类操作中的 两两不同。
记 为第一类操作的数量。
本题共 个测试点,每个测试点 分。
| 测试点编号 | 分值 | 约束条件 |
|---|---|---|
| 对所有第一类操作,均有 ,且 | ||
| 第一类操作中的 按操作时间严格递增,且对每个第二类操作, 不小于此前所有第一类操作中的最大 | ||
| 第一类操作中的 按操作时间严格递增 | ||
| 每次查找访问到的非空节点数量不超过 | ||
| 无额外限制 |