全国信息学奥林匹克联赛(NOIP2014)复赛 模拟题Day2 长乐一中
2016-11-15 13:56
267 查看
题目名称 | 改造二叉树 | 数字对 | 交换 |
英文名称 | 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 | 无 | 无 | 无 |
【题目描述】
小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。
什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch,则key[p]<key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。
小Y与他人讨论的内容则是,现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数(可以是负整数或0),所要的最少修改次数。
相信这一定难不倒你!请帮助小Y解决这个问题吧。
【输入格式】
第一行一个正整数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一定是二叉树的根。
【输出格式】
仅一行包含一个整数,表示最少的修改次数。
【样例输入】
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.
T1:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; const int N = 52, Mod = 1e9 + 7; int n, p , dp , C ; int Dfs(int len, int low) { if (dp[len][low] != -1) return dp[len][low]; if (len == 1) return dp[len][low] = 1; int &res = dp[len][low]; res = 0; int t , m = 0, j, k; for (int i = 1; i <= n; ++i) if (p[i] >= low && p[i] < low + len) t[++m] = p[i]; for (int i = 1; i < m; ++i) { swap(t[i], t[i + 1]); for (j = 1; j <= i; ++j) if (t[j] >= low + i) break; for (k = i + 1; k <= m; ++k) if (t[k] < low + i) break; if (j > i && k > m) { ll tmp = (ll)Dfs(i, low) * Dfs(m - i, low + i) % Mod; tmp = tmp * C[m - 2][i - 1] % Mod; res = (res + tmp) % Mod; } swap(t[i], t[i + 1]); } return res; } int main() { freopen("swap.in", "r", stdin); freopen("swap.out", "w", stdout); scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &p[i]); memset(dp, -1, sizeof(dp)); for (int i = 0; i <= n; ++i) { C[i][0] = 1; for (int j = 1; j <= i; ++j) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % Mod; } Dfs(n, 0); if (dp [0] != -1) cout << dp [0] << endl; else puts("0"); fclose(stdin); fclose(stdout); return 0; }
View Code
相关文章推荐
- 全国信息学奥林匹克联赛 ( NOIP2014) 复赛 模拟题 Day1 长乐一中
- 正确答案 全国信息学奥林匹克联赛( ( NOIP2014) 复 赛 模拟题 Day1 长乐一中
- 全国信息学奥林匹克联赛(NOIP2011)复赛 提高组 day2 T2 聪明的质监员
- 全国信息学奥林匹克联赛(NOIP2010)复赛 3.导弹拦截 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 题目
- CCF全国信息学奥林匹克联赛(NOIP2016)复赛模拟提高组 day2 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 1.数字统计 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 2.接水问题 解题报告
- 全国信息学奥林匹克联赛NOIP计算机基础知识
- 全国信息学奥林匹克联赛(NOIP2016 )复赛模拟(二)
- 全国信息学奥林匹克联赛(NOIP2016 )复赛模拟(三)
- NOIP2014复赛提高组day2(A:无线网络发射器选址 B:寻找道路 C:解方程)
- 2015年信息学奥林匹克联赛-复赛流程
- NOIP2016全国信息学分区联赛提高组第二试 组合问题
- 全国青少年信息学奥林匹克分区联赛(N)竞赛大纲
- NOIP2016全国信息学分区联赛提高组第二试 蚯蚓
- 2017河南省信息学奥林匹克联赛复赛监考日志--CCF NOIP
- NOIP2016全国信息学分区联赛提高组第二试 蚯蚓 ssl 2599 队列
- NOIP2016全国信息学分区联赛提高组第二试 蚯蚓
- 全国青少年信息学(计算机)奥林匹克分区联赛竞赛大纲