某次模拟赛
Posted 小飞淙的云端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了某次模拟赛相关的知识,希望对你有一定的参考价值。
题目描述 Description |
小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。 什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch,则key[p]<key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。 小Y与他人讨论的内容则是,现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数(可以是负整数或0),所要的最少修改次数。 相信这一定难不倒你!请帮助小Y解决这个问题吧。 |
输入描述 Input Description |
第一行一个正整数 n 表示二叉树结点数。结点从 1~n 进行编号。 第二行 n 个正整数用空格分隔开,第 i 个数 ai 表示结点 i 的原始数值。 此后 n - 1 行每行两个非负整数 fa, ch,第 i + 2 行描述结点 i + 1 的父亲编号 fa,以及父子关系 ch,(ch = 0 表示 i + 1 为左儿子,ch = 1 表示 i + 1 为右儿子)。 结点 1 一定是二叉树的根。 |
输出描述 Output Description |
仅一行包含一个整数,表示最少的修改次数。 |
样例输入 Sample Input |
3 |
样例输出 Sample Output |
2 |
数据范围及提示 Data Size & Hint |
20 % :n <= 10 , ai <= 100.
40 % :n <= 100 , ai <= 200 |
之前的一些废话:博客停更一个月,中间出国了两周,然后刷暑假作业,上了一周竞赛,顺便刷完了X战警系列电影。
题解:首先明确一下二叉树的三种遍历方式:先序遍历,中序遍历,后序遍历
void dfs(int o) { //在这里操作是先序遍历 dfs(ch[0][o]); //在这里操作是中序遍历 dfs(ch[1][o]); //在这里操作是后序遍历 }
如果一个二叉树满足二叉搜索树的性质的话,我们发现当且仅当中序遍历的时候是严格上升子序列的时候满足二叉搜索树的性质。所以我们先把中序遍历给计算出来,然后转化成了这样一个问题:对于一个序列,修改其中每个数的数值,问最少几次操作使得原序列变成严格上升子序列。
很容易想到跟最长上升子序列有一些关系,但还是有一点不一样,假如某一段序列是这样的:1,6,7,2,3,4,5,该序列的最长上升子序列为1,2,3,4,5所以需要对6,7进行修改,
代码:
总结:
以上是关于某次模拟赛的主要内容,如果未能解决你的问题,请参考以下文章