今天做题下来,体会最深的是结构体
首先我们需要会结构体
然后可以灵活运用深度优先dfs
下面是我会练习的一部分题,一些题我会放题解
接下来介绍一下二叉树
二叉树是每个结点最多有两个子树的树结构。
也就是说二叉树不允许存在度⼤于2的树。它有五种最基本的形态:二叉树可以是空集。根可以有空的左子树或者右子树;或者左右子树都是空。其中只有左子树或者右子树的叫做斜树
练习题
P4715 【深基16.例1】淘汰赛
题目描述
有 2^n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。给出各个国家的能力值,请问亚军是哪个国家?
输入格式
第一行一个整数 n,表示一共 2^n 个国家参赛。
第二行 2^n 个整数,第 i个整数表示编号为 i的国家的能力值(1≤i≤2^n)。
数据保证不存在平局。
输出格式
仅一个整数,表示亚军国家的编号。
#include<bits/stdc++.h>
using namespace std;
int n;
struct g{
int num;
int ant =0;
};
int main()
{
cin >> n;
g maxl,maxr;
g a;
for(int i=1;i<=pow(2,n)/2;i++){
cin >> a.ant;
if(a.ant > maxl.ant){
maxl.ant = a.ant;
maxl.num = i;
}
}
for(int i=pow(2,n)/2+1;i<=pow(2,n);i++){
cin >> a.ant;
if(a.ant>maxr.ant){
maxr.ant = a.ant;
maxr.num = i;
}
}
if(maxl.ant > maxr.ant)
cout << maxr.num;
else
cout << maxl.num;
return 0;
}
思路:把参加的国家均分为两部分,选出前部分最高的能力值和后部分的最高能力值作比较,输出较小的那个就是亚军
(现在想一想,好像不用结构体也可以记录号码,用一个变量来记录就可以了)
P4913 【深基16.例3】二叉树深度
题目描述
有一个 n(n≤106) 个结点的二叉树。给出每个结点的两个子结点编号(均不超过 n),建立一棵二叉树(根节点的编号为 1),如果是叶子结点,则输入 0 。
建好这棵二叉树之后,请求出它的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。
输入格式
第一行一个整数 n,表示结点数。
之后 n 行,第 i 行两个整数 l、r,分别表示结点 i的左右子结点编号。若 l=0 则表示无左子结点,r=0同理。
输出格式
一个整数,表示最大结点深度。
#include<bits/stdc++.h>
using namespace std;
int n;
int maxn =-1;
struct g1{
int l,r;
}g[1000005];
void dfs(int x,int y)
{
if(x==0) return;
maxn = max(maxn,y);
dfs(g[x].l,y+1);
dfs(g[x].r,y+1);
}
int main()
{
cin >> n;
for(int i=1;i<=n;i++)
cin >> g[i].l>>g[i].r;
dfs(1,1);
cout << maxn;
return 0;
}
这题用到了深度优先和结构体,结构体来记录左右子结点,方便访问
思路就是一条路走到底,之后再返回上一层走上个结点的右子树
每下一层y就+1 ,而maxn 记录最远的一次
P1827 [USACO3.4] 美国血统 American Heritage
题目描述
农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。
你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:
C
/ \
/ \
B G
/ \ /
A D H
/ \
E F
树的中序遍历是按照左子树,根,右子树的顺序访问节点。
树的前序遍历是按照根,左子树,右子树的顺序访问节点。
树的后序遍历是按照左子树,右子树,根的顺序访问节点。
输入格式
第一行: 树的中序遍历
第二行: 同样的树的前序遍历
输出格式
单独的一行表示该树的后序遍历。
#include<bits/stdc++.h>
using namespace std;
string a,b;
void dfs(int l1,int l2,int l3,int l4){
if(l1>l2||l3>l4)
return;
for(int i=l1;i<=l2;i++)
if(a[i]==b[l3]){
dfs(l1,i-1,l3+1,l3+i-l1);
dfs(i+1,l2,l3+i-l1+1,l4);
cout<<a[i];
}
}
int main()
{
cin>>a>>b;
int l=a.size();
dfs(0,l-1,0,l-1);
return 0;
}
(俺不会qaq)
题解先放着
P5076 【深基16.例7】普通二叉树(简化版)
题目描述
您需要写一种数据结构,来维护一些数( 都是 10^9以内的数字)的集合,最开始时集合是空的。其中需要提供以下操作,操作次数 q 不超过 10^4:
查询 x 数的排名(排名定义为比当前数小的数的个数 +1。若有多个相同的数,应输出最小的排名)。
查询排名为 x 的数。
求 x 的前驱(前驱定义为小于 x,且最大的数)。若未找到则输出 -2147483647。
求 x 的后继(后继定义为大于 x,且最小的数)。若未找到则输出 2147483647。
插入一个数 x。
输入格式
第一行是一个整数 q,表示操作次数。
接下来 q 行,每行两个整数 op,x,分别表示操作序号以及操作的参数 x。
输出格式
输出有若干行。对于操作 1,2,3,4,输出一个整数,表示该操作的结果。
用数组写了一下,过了案例,赶紧去交,没过,狠狠的伤心了(qaq)
(没过我也放在这,当个反例)
#include<bits/stdc++.h>
using namespace std;
int q;
int k=0;
int a[10005];
int one(int y){
for(int i=1;i<=k;i++)
{
if(a[i]==y){
return i;
}
}
}
int two(int y)
{
return a[y];
}
int three(int y)
{
for(int i=1;i<=k;i++)
{
if(a[i]==y){
return a[i-1];
}
}
return -2147483647;
}
int four(int y)
{
for(int i=1;i<=k;i++)
{
if(a[i]==y){
return a[i+1];
}
}
return 2147483647;
}
int main()
{
cin >> q;
int x,y;
for(int i =1;i<=q;i++)
{
cin >> x >> y;
if(x==5)
{
k++;
a[k] = y;
sort(a+1,a+k+1);
}
if(x==1){
cout << one(y) <<endl;
}
if(x==2){
cout << two(y) << endl;
}
if(x==3){
cout << three(y) << endl;
}
if(x==4)
cout << four(y) <<endl;
}
return 0;
}