【NOIP模拟考三】线段树/ST表 day2 second 二叉树
来源:互联网 发布:网络歌曲女生唱的 编辑:程序博客网 时间:2024/05/22 01:53
题目描述
给定一棵二叉树,节点标号从1到n。在不改变其中序遍历的情况下,请改变树的结构,使得这棵二叉树的先序遍历(前序遍历)字典序最小。
输入
第一行一个整数n,表示二叉树的节点数。
接下来n行,每行两个整数。第i行的两个整数表示编号为i的节点的左儿子和右儿子的编号(不存在即为0)。
输出
输出一行n个整数,表示不改变中序遍历的情况下字典序最小的前序遍历序列。
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
55 40 02 10 00 0
样例输出
1 2 3 5 4
提示
1 3 N/A
2 4 N/A
3 10 N/A
4 100 树为一条链,且只存在右儿子关系。
5 1000 给出的树满足排序二叉树的性质。即任意一个节点
6 100000 左子树中所有值<该节点<右子树中所有值。
7 65535 满二叉树
8 100000 N/A
9 100000 N/A
咳咳,我还是要填坑的。。。
考试时这道题还是想了很久,想过各种诡异的方法,比如LCA啦、平衡树啦、暴力啊。。。什么都有,后来才恍然大悟——这题好水。。。
我们要让中序遍历的顺序不变,却不知道中序遍历的结果是什么,怎么可以呢,是吧……所以第一步应该中序遍历!
我们就举样例的例子吧!
好久没有看到图片了,是不是很激动?
很容易发现,我们只需要让根最小就是最优的,那么我们很显然要1当根。其次,显然的,根的左儿子最小就最好,于是我们把2当做1的左儿子,但是,尽管样例是可以的,却并不代表所有数据都可以,别忘了中序遍历的限制!
很容易发现,只要是中序遍历根左边的,就可以当成是左儿子,那么我们可以在根左边的中选出一个最小的来当根的左儿子,然后同样的在右边选一个最小的当右儿子,用线段树维护区间最小值就好了啦……(当然ST表也是可以的……)
所以样例就很容易解释了——先选1,在左边选择最小的2,2没有左边,于是在右边选择最小的3,3也没有左边,于是在右边选择最小的5,这时1的左子树完毕,在右边选择最小的4,整棵树完毕。按遍历顺序依次输出:
1 2 3 5 4
PS:这道题虽然是求先序遍历,其实完全不需要再建一棵树,只要假想有那么一棵树就可以了……
好了,一如既往的代码……
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100005int n,ls[N],rs[N],fa[N],r;int mid[N],wz[N],tim;void dfs(int r){ if(ls[r]) dfs(ls[r]); mid[++tim]=r; wz[r]=tim; if(rs[r]) dfs(rs[r]);}struct ST{ int l,r,minn;}s[4*N-15];void make(int l,int r,int q){ s[q].l=l;s[q].r=r; if(l<r) { int mid=(l+r)>>1; make(l,mid,q<<1); make(mid+1,r,q<<1|1); }}void insert(int a,int k,int q){ if(s[q].l==k&&s[q].r==k) { s[q].minn=a; return; } if(k>((s[q].l+s[q].r)>>1)) insert(a,k,q<<1|1); else insert(a,k,q<<1); s[q].minn=min(s[q<<1].minn,s[q<<1|1].minn);}int minn(int l,int r,int q){ if(l==s[q].l&&r==s[q].r) return s[q].minn; int mid=(s[q].l+s[q].r)>>1; if(r<=mid) return minn(l,r,q<<1); if(l>mid) return minn(l,r,q<<1|1); return min(minn(l,mid,q<<1),minn(mid+1,r,q<<1|1));}void getans(int l,int r){ if(l>r) return; int now=minn(l,r,1); int p=wz[now]; printf(" %d",now); getans(l,p-1); getans(p+1,r);}int main(){ //freopen("bitree.in","r",stdin); //freopen("bitree.out","w",stdout); scanf("%d",&n); make(1,n,1); for(int i=1;i<=n;i++) { scanf("%d%d",&ls[i],&rs[i]); if(ls[i]) fa[ls[i]]=i; if(rs[i]) fa[rs[i]]=i; } for(int i=1;i<=n;i++) if(!fa[i]) { r=i; break; } dfs(r); for(int i=1;i<=n;i++) insert(mid[i],i,1); printf("1"); getans(1,wz[1]-1); getans(wz[1]+1,n);}
阅读全文
0 0
- 【NOIP模拟考三】线段树/ST表 day2 second 二叉树
- 【NOIP模拟考三】水资源 day2 first 序列计数
- 【NOIP模拟考三】无向图的桥 day1 second 荒岛野人
- NOIP模拟题 [模拟][DP][线段树]
- NOIP 2017 Day2 题3:队列 线段树
- NOIP 模拟题 friendly [最小生成树] [ST在线] [hash]
- 洛谷 NOIP 模拟 DAY2
- 【NOIP模拟】被粉碎的线段树
- EZOI NOIP模拟赛 线段树
- [NOIP模拟题][树状数组][线段树]
- 【NOIP模拟题】[状压dp][线段树]
- NOIP模拟 排列【权值线段树】
- NOIP模拟 shopping【线段树 or Splay】
- NOIP模拟 序列操作【线段树】
- NOIp模拟赛-改造二叉树
- 【NOIP模拟考一】 贪心 second 排座椅(seat.cpp)
- nyoj1068 ST 线段树
- 2- noip模拟赛 DAY2
- 设计模式之适配器模式
- 输入输出挂
- Django启动服务器报错:maximum recursion depth exceeded in cmp
- CentOS7 minimal*xfce+Win10 双系统配置过程记录
- MOOC清华《面向对象程序设计》第3章:移动构造函数实验
- 【NOIP模拟考三】线段树/ST表 day2 second 二叉树
- springmvc之上传图片
- DOS命令与批处理学习历程
- spring中关于对jdbc.properties使用的两种配置方式
- 剑指offer 3---二维数组的查找
- [编程题] 洗牌
- Symfony Twig模板引擎——基础知识总结
- [POJ 3259] Wormholes [SPFA]
- Java出现null指针的九种情况