【NOIP模拟题】【DP】【LIS】【中缀表达式】2016.11.15 第一题 小L的二叉树 题解
2016-11-15 16:44
330 查看
小L的二叉树
小L的二叉树题目背景
勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利。但是,小L对数据结构的掌握实在十分渣渣。
所以,小L当时卡在了二叉树。
【题目描述】
在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch,则key[p] < key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。(因为小L十分喜欢装xx,所以这里他十分装xx的给大家介绍了什么是二叉树和二叉搜索树)。
可是善于思考的小L不甘于只学习这些基础的东西。他思考了这样一个问题:现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数(可以是负整数或0),所要的最少修改次数。
这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/16哦!
【输入格式】 第一行一个正整数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为右儿子)。 为了让你稍微减轻些负担,小L规定:结点1一定是二叉树的根哦!
【输出格式】 仅一行包含一个整数,表示最少的修改次数。
【样例输入】
3
2 2 2
1 0
1 1
【样例输出】 2
【数据范围】
20 % :n <= 10 , ai <= 100.
40 % :n <= 100 , ai <= 200
60 % :n <= 2000 .
100 % :n <= 10 ^ 5 , ai < 2 ^ 31.
小L,是
回到正题,这道题先用中序遍历再跑LIS,但是这是有问题的!!!!!看了好多博客都没指出,因为它要求全是整数,所以我们要再做一些小手脚。a1, a2, a3, a4 . an 映射成:a1 - 1, a2 - 2, a3 - 3, a4 - 4 . an - n.这样以后再求一遍LIS长度就finish。
附代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #define LL long long #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; const int maxn = 1e5+5; int n,tot,ans; int dp[maxn],f[maxn]; struct node { int l,r,fa,num; }a[maxn]; template <class T> inline void read(T &xx) { xx = 0; T flag = 1; char ch = (char)getchar(); while(ch<'0' || ch>'9') { if(ch == '-') flag = -1; ch = (char)getchar(); } while(ch>='0' && ch<='9') { xx = (xx<<1) + (xx<<3) + ch - '0'; ch = (char)getchar(); } xx *= flag; } void init() { read(n); for(int i = 1; i <= n; i++) read(a[i].num); for(int i = 2; i <= n; i++) { int k; read(a[i].fa); read(k); if(!k) a[a[i].fa].l = i; else a[a[i].fa].r = i; } } void dfs(int i) { if(i == 0) return; dfs(a[i].l); dp[++tot] = a[i].num; dfs(a[i].r); } int LIS() { int top = 0; for(int i = 1; i <= n; i++) { if(top == 0 || dp[i] >= f[top]) f[++top] = dp[i]; else { int l = 1, r = top; while(l <= r) { int mid = (l + r) >> 1; if(f[mid] > dp[i]) r = mid - 1; else l = mid + 1; if(f[mid] == dp[i]) { while(f[mid] == dp[i]) mid++; l = mid; break; } } f[l] = dp[i]; } } return top; } void work() { dfs(1); for(int i = 1; i <= n; i++) dp[i] -= i; ans = n-LIS(); } int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); init(); work(); printf("%d",ans); return 0; }
相关文章推荐
- 【NOIP模拟题】【DP】【同余最短路】【暴力剪枝】2016.11.15 第二题 小L的牛栏 题解
- 【NOIP模拟题】【最短路】【DP】2016.11.11第一题tractor题解
- [NOIP模拟题][LIS][同余最短路][DP][矩阵快速幂][容斥原理]
- NOIP模拟题 2016.11.15 [LIS] [spfa] [同余最短路] [矩阵快速幂] [容斥原理] [数学]
- 【NOIP模拟题】【模拟】【DP】【JOI】2016.11.14第一题 复制&粘贴2 题解
- NOIP模拟题 [模拟][DP][线段树]
- 【NOIP模拟题】【动态规划DP】2016.11.11第二题Landscaping题解
- 【NOIP模拟题】【贪心】【动态规划DP】2016.11.12第二题题解
- 【NOIP模拟题】【数学归纳法】【容斥原理】2016.11.18 第一题 信 题解
- 【NOIP模拟题】【数学归纳法】【递推】【容斥原理】【等比数列求和】2016.11.15 第三题 小L的珍珠挂饰 题解
- 【NOIP模拟题】【暴力求解法】2016.11.17 第一题 素数密度 题解
- NOIP模拟题[递推][并查集][DP]
- ACM 106. [NOIP2003] 加分二叉树(区间dp)
- 【树形DP】[NOIP2003]加分二叉树
- 【Noip模拟】【dp】【LIS】【矩阵快速幂】
- 【NOIP模拟题】【DP】【快速幂】2016.11.16 第二题
- 【NOIP模拟题】【数学归纳法】2016.11.10第一题题解
- NOIP模拟题 [递推][DP][搜索]
- NOIP模拟题 2016.9.3 [数论] [逆序对] [树状数组] [树形dp]
- [线性DP]合唱队形(NOIP2004)(LIS的简单应用)