JZOJ 3894. 改造二叉树

题目

Description

小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。
什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch,则key[p]<key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。
小Y与他人讨论的内容则是,现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数(可以是负整数或0),所要的最少修改次数。
相信这一定难不倒你!请帮助小Y解决这个问题吧。

Input

第一行一个正整数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

仅一行包含一个整数,表示最少的修改次数。

Sample Input

32 2 21 01 1

Sample Output

2

Data Constraint

20 % :n <= 10 , ai <= 100.
40 % :n <= 100 , ai <= 200
60 % :n <= 2000 .
100 % :n <= 10 ^ 5 ,  ai < 2 ^ 31.

分析

20% :暴力。 40% :可以用 DP 或者贪心或者神奇的暴力等其他奇怪的方法完成。 60% :正解的 LIS 打成 O(n ^ 2)。 100% :首先求出这颗二叉树的中序遍历,那么问题就转换成用最少的修改次数使这个整 数序列严格单调递增。于是很自然的想到了 LIS,但单纯用 LIS 是有一些问题的, 比如这种情况:2 3 1 4, LIS 为 2 3 4,答案求出来为 1,但由于整数的限制,应该 要修改 2 次。即直接 LIS 求出的答案是在非严格递增的情况下的答案。 所以我们将原序列稍加修改,一个常见的将严格递增整数序列映射成非严格递增整 数序列的技巧就是将如下序列: a1, a2, a3, a4 ... an 映射成: a1 - 1, a2 - 2, a3 - 3, a4 - 4 ... an - n. (这种方法常见于计数类问题)。 这样映射后求最长不下降子序列的长度就没问题了。

代码

 1 #include<iostream>
 2 #include<fstream>
 3 #include<algorithm>
 4 #define N 500001
 5 using namespace std;
 6 int n;
 7 struct sb
 8 {
 9     int val,l,r;
10 }a[N];
11 int cs=0;
12 int f[N];
13 void dfs(int p)
14 {
15     if (p==0) return;
16     dfs(a[p].l);
17     f[++cs]=a[p].val;
18     dfs(a[p].r);
19 }
20 int b[N];
21 int ef(int l,int r,int p)
22 {
23     while (l<=r)
24     {
25         int mid=(l+r)/2;
26         if (b[mid]<=p)
27             l=mid+1;
28         else
29             r=mid-1;
30     }
31     return l;
32 }
33 int len=1;
34 void lis()
35 {
36     b[1]=f[1];
37     for (int i=2;i<=n;i++)
38     {
39         if (f[i]>=b[len])
40             b[++len]=f[i];
41         else
42         {
43             int wz=ef(1,len-1,f[i]);
44             b[wz]=f[i];
45         }
46     }
47 }
48 int main ()
49 {
50     cin>>n;
51     for (int i=1;i<=n;i++)
52         cin>>a[i].val;
53     int x,ch;
54     for (int i=2;i<=n;i++)
55     {
56         cin>>x>>ch;
57         if (ch==0)
58            a[x].l=i;
59         else
60            a[x].r=i;
61     }
62     dfs(1);
63     for (int i=1;i<=n;i++)
64        f[i]-=i;
65     lis();
66     cout<<n-len;
67 }

原文地址:https://www.cnblogs.com/zjzjzj/p/10321843.html

时间: 2024-10-31 14:01:16

JZOJ 3894. 改造二叉树的相关文章

10.26最后的模拟:改造二叉树

改造二叉树 [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树. 什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch]:若其存在右孩子rch,则key[p]<key[rch]:注意,本题中的二叉搜索树应满足对于所有结点,其左子树

改造二叉树

题目背景 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣. 所以,小L当时卡在了二叉树. 题目描述 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树.什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch]:若其存在右孩子rch,则k

P3365 改造二叉树

题目背景 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣. 所以,小L当时卡在了二叉树. 题目描述 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树.什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch]:若其存在右孩子rch,则k

10day2

最多因子数 搜索 [问题描述] 数学家们喜欢各种类型的有奇怪特性的数.例如,他们认为 945 是一个有趣的数,因为它是第一个所有约数之和大于本身的奇数. 为了帮助他们寻找有趣的数,你将写一个程序扫描一定范围内的数,并确定在此范围内约数个数最多的那个数.不幸的是,这个数和给定的范围的都比较大,用简单的方法寻找可能需要较多的运行时间.所以请确定你的算法能在几秒内完成最大范围内的扫描. [输入] 只有一行,给出扫描的范围,由下界 L 和上界 U 确定.满足 2≤L≤U≤1000000000. [输出]

8.12联考题解

所谓今天的题格外水,dalao们纷纷AK--但是本蒟蒻并没有看出来有多水啊--虽然还是水过了一道题,然后剩下的题就照常地转不过来弯,分数和往常并没有多大变化= =. 灌水 时间限制:1s 空间限制:256MB 样例输入1: 3 1 样例输出1: 3 1 2 样例输入2: 4 1 样例输出2: 4 3 1 2 样例输入3: 8 17 样例输出3: 6 2 3 1 8 4 5 7 题解       这个题,第一眼看过去很interesting,第二眼看过去一脸茫然--头一遍读题的时候看到数据范围里那

NOIP2017SummerTraining0717

个人感受:自己水平是真的差劲,和他们不是一个档次的,第二题,如果不是陈载元暴力过了,我也不会那么早去A了第二题,第一题真的是无语,以前做到过,还想到了每个对应值a[i]-i,但是没想出来,真的是 可惜,这套题的话前两题都比提高组的要水,但这样下去,别说省选,TG一等都难拿. 改造二叉树 时间限制: 1 Sec  内存限制: 256 MB提交: 365  解决: 95[提交][状态][讨论版] 题目描述 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树

二模10day2解题报告

T1.最多因子数(divisors) 给出范围l,r求其中约数和最大的最小整数. 非常深井冰的题目:如果特判加暴力的话分数低的可怜 AC做法要用到分解质因数和线性筛(这俩好写),然而,一个一个枚举还是不可避免的TLE了(最后一个点1,1000000000可怕). 其实考虑一下,如果n为合数且是x的约数,那么n的约数也是x的约数,所以重复计算了很多.要避免这种情况就要改dfs,在计算过程中保存最多的和最多的约数个数.(然而并不是那么好打的) T2.改造二叉树(bst) 给出n个节点的二叉树,以及每

常用排序算法的python实现和性能分析

http://www.cnblogs.com/wiki-royzhang/p/3614694.html 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整了一下,可以阶段性的留下些脚印——没办法,平时太忙,基本上没有时间写博客.面试测试开发的话,这些也许能帮得上一些. 这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数

9.2noip模拟试题

  题目名称 改造二叉树 数字对 交换 英文名称 binary pair swap 输入文件名 binary.in pair.in swap.in 输出文件名 binary.out pair.out swap.out 时间限制 1s 2s 1s 空间限制 256M 256M 256M 测试点数目 20 20 10 测试点分值 5 5 10 是否有部分分 无 无 无 题目类型 传统 传统 传统 是否有SPJ 无 无 无 1.改造二叉树 [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科