上链接:【深基16.例1】淘汰赛 - 洛谷https://www.luogu.com.cn/problem/P4715
上题干:
题目描述
有 2^n(n≤7)个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。给出各个国家的能力值,请问亚军是哪个国家?
输入格式
第一行一个整数 n,表示一共 2^n 个国家参赛。
第二行 2^n 个整数,第 i 个整数表示编号为 i 的国家的能力值(1≤i≤2^n)。
数据保证不存在平局。
输出格式
仅一个整数,表示亚军国家的编号。
输入输出样例
输入 #1复制
3 4 2 3 1 10 5 9 7输出 #1复制
1
写这道题,我们可以先将题目给的样例画出来。大概是这样的:
我们可以发现,从最顶部的冠军开始(二叉树的根结点),它的在下一层有两个国家(分支),而且每个国家的下面又有两个国家。直到达到最底部(叶节点)没有分支了。
每个结点的左右两边叫做左子树,右子树。每个左子树,右子树又是一个二叉树,这样的结构就是满二叉树。
我们可以画出:这道题的满二叉树的图像
根据这两张图,我们就可以写出这道题。
首先,我们把所有的数值,放进二叉树的叶结点,也就是最下面一层。
定义一个战斗力数组 able[N],N的取值取决于数据范围。
然后存入每个国家的战斗力,由我们的第一张图可知,8的位置是国家1,9的位置是国家2,以此类推。和每个国家的编号。
然后存入之后,开始dfs:
直到遍历到从树的底部的上一层,该结点的左右子树。如图:
if(该数的左结点战斗力>右结点) 该数的战斗力就是 左结点战斗力,该数的编号,就是左节点的编号。
以此类推,直到遍历 所有结点。
最后在比较结点2,结点3的战斗力,就可以得到亚军的编号。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cctype>
#include<map>
#include<set>
#include<queue>
using namespace std;
const int N =1e5;
int able[N];
int win[N];
int n;
void dfs(int x)
{
if (x >= 1 << n)return;
else {
dfs(2 * x);
dfs(2 * x + 1);
int left = 2 * x, right = 2 * x + 1;
if (able[left] > able[right]) {
able[x] = able[left];
win[x] = win[left];
}
else {
able[x] = able[right];
win[x] =win[ right];
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < 1 << n; i++)
{
cin >> able[i + (1 << n)];
win[i + (1 << n)] = i + 1;
}
dfs(1);
able[2] < able[3] ? cout << win[2] : cout << win[3];
}