选拔赛3---7-10 红豆生南国

有诗云:

    相思 (王维  唐)
        
红豆生南国, 春来发几枝。

愿君多采撷, 此物最相思。

那么,我们来采红豆吧!

假设红豆树是这个样子的:

这种红豆树的特点是:

  • 每个结点都有一个正整数编号,标在结点内部。结点的编号各不相同。
  • 最上方一层结点是 红豆(图中红圈所示的5个结点),这一层被称之为红豆层。
  • 树的根结点、左子结点、右子结点、左子树、右子树等的定义与“数据结构”中的“二叉树”相同,但它毕竟是“自然界中的树”,树根在最下方,如图中的结点5
  • 图中这棵红豆树是“完全二叉红豆树”,类似“数据结构”中的“完全二叉树”。(“完全二叉树”的定义:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于一个有N个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树) 从图上看,就是:要么每一层(包括红豆层)的结点数达到最大值,要么只在红豆层的最右边缺少一些结点。

对于红豆树,我们定义两种遍历顺序:

  1. 正序遍历:先访问树根结点,再正序遍历其左子树,最后正序遍历其右子树
  2. 逆序遍历:先逆序遍历其右子树,再逆序遍历其左子树,最后访问树根结点

对于给定的一棵完全二叉红豆树以及一些要采撷的结点,计算每次采撷能采到的红豆数量。

注意:我们采的点,可能是红豆,也可能不是红豆。采撷一个结点的意思是,把这个结点及这个结点的子树的全部结点从树中采下来。

例如:若采结点7,这是红豆结点,我们将获得1颗红豆;若采结点11,这不是红豆结点(而是一个枝结点!),我们将获得红豆树的一枝,包含2个红豆结点(8和2)。

输入格式:

输入有四行。

第一行是一个不超过60的正整数N,表示完全二叉红豆树中的结点数量。

第二行是N个不超过1000的结点编号序列,以空格间隔,表示的是这棵树的逆序遍历序列。

第三行是一个不超过N的正整数K,表示进行K次采撷。

第四行是K个正整数,依次表示每次要采的结点编号。

输出格式:

输出包含K+1行,

前K行,对于输入的每个采撷的点,在一行输出相应获得的红豆数量。如果这个点已经被采掉了,则输出Zao Jiu Cai Diao Le!。如果这个点在原树中根本不存在,则输出Kan Qing Chu Le?

最后一行,输出采撷结束之后,这棵红豆树的正序遍历序列,用空格分隔,最后一个结点之后没有空格。如果采撷结束之后树已空,则输出Kong Le!

输入样例1:

对于题目中给出的图,对应的输入是:

12
10 4 3 12 6 7 1 2 8 11 9 5
4
15 12 11 2

输出样例1:

Kan Qing Chu Le?
1
2
Zao Jiu Cai Diao Le!
5 9 1 7 6

输入样例2:

对于题目中给出的图,对应的输入是:

12
10 4 3 12 6 7 1 2 8 11 9 5
1
5

输出样例2:

5
Kong Le!

 这题的建树方法值得学

void build(int u)
{
	if(u>n) return;
	build(2*u+1);
	build(2*u);
	cin>>tr[u];
	id[tr[u]]=u;
}

选拔赛的时候我建树建了半天 ,最后只拿六分,题意都理解错了(以后碰到这种题先跳过,看看三阶题有没有能写的。

 这题我以为果子个数为0就是被摘过了,但不是这样的,我们需要用一个st数组记录一下这个点有没有被摘过。

贴一下完整代码

#include<bits/stdc++.h>
using namespace std;
const int N=150;
typedef long long LL;
int tr[N];
map<int,int>id;
bool st[N];
int n,low;
bool flag=true;
void build(int u)
{
	if(u>n) return;
	build(2*u+1);
	build(2*u);
	cin>>tr[u];
	id[tr[u]]=u;
}
int Delete(int u)
{
	if(u>n||st[u]) return 0;
	int cnt=u>low;
	st[u]=true;
	cnt+=Delete(2*u)+Delete(2*u+1);
	return cnt;
}
void preOrder(int u)
{
	if(u>n||st[u]) return;
	if(flag)
	{
		flag=false;
		cout<<tr[u];
	}else cout<<" "<<tr[u];
	preOrder(2*u);
	preOrder(2*u+1);
}
int main()
{
	cin>>n;
	low=pow(2,(int)(log(n)/log(2)+1e-8))-1;
	build(1);
	int k;
	cin>>k;
	while(k--)
	{
		int x;
		cin>>x;
		if(!id.count(x)) puts("Kan Qing Chu Le?");
		else 
		{
			x=id[x];
			if(st[x]) puts("Zao Jiu Cai Diao Le!");
			else cout<<Delete(x)<<endl;
		}
	}
	preOrder(1);
	if(flag) puts("Kong Le!");
	return 0;
}

 

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值