AtCoder题解 —— AtCoder Beginner Contest 188 —— C - ABC Tournament —— 数据结构之二叉树

题目相关

题目链接

AtCoder Beginner Contest 188 C 题,https://atcoder.jp/contests/abc188/tasks/abc188_c

Problem Statement

2 N 2^N 2N players, labeled 1 1 1 through 2 N 2^N 2N, will compete against each other in a single-elimination programming tournament.
The rating of Player i i i is A i A_i Ai. Any two players have different ratings, and a match between two players always results in the victory of the player with the higher rating.
The tournament looks like a perfect binary tree. Formally, the tournament will proceed as follows:

  • For each integer i = 1 , 2 , 3 , … , N i=1,2,3,…,N i=1,2,3,,N in this order, the following happens.
    • For each integer j ( 1 ≤ j ≤ 2 N − i ) j(1≤j≤2^{N−i}) j(1j2Ni), among the players who have never lost, the player with the ( 2 j − 1 ) (2j−1) (2j1)-th smallest label and the player with the 2 j 2j 2j-th smallest label play a match against each other.

Find the label of the player who will take second place, that is, lose in the final match.

Input

Input is given from Standard Input in the following format:
N N N
A 1 A 2 ⋯ A 2 N A_1 A_2 \cdots A_{2^N} A1A2A2N

Output

Print the label of the player who will take second place.

Sample 1

Sample Input 1

2
1 4 2 5

Sample Output 1

2

Explaination

First, there will be two matches between Players 1 1 1 and 2 2 2 and between Players 3 3 3 and 4 4 4. According to the ratings, Players 2 2 2 and 4 4 4 will win.
Then, there will be a match between Players 2 2 2 and 4 4 4, and the tournament will end with Player 4 4 4 becoming champion.
The player who will lose in the final match is Player 2 2 2, so we should print 2 2 2.

Sample 2

Sample Input 2

2
3 1 5 4

Sample Output 2

1

Explaination

First, there will be two matches between Players 1 1 1 and 2 2 2 and between Players 3 3 3 and 4 4 4. According to the ratings, Players 1 1 1 and 3 3 3 will win.
Then, there will be a match between Players 1 1 1 and 3 3 3, and the tournament will end with Player 3 3 3 becoming champion.
The player who will lose in the final match is Player 1 1 1, so we should print 1 1 1.

Sample 3

Sample Input 3

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

Sample Output 3

2

Constraints

  • 1 ≤ N ≤ 16 1≤N≤16 1N16
  • 1 ≤ A i ≤ 1 0 9 1≤A_i≤10^9 1Ai109
  • A i A_i Ai are pairwise different.
  • All values in input are integers.

题解报告

题目翻译

2 N 2^N 2N 个玩家,编号从 1 1 1 2 N 2^N 2N。这些玩家正在进行一对一编程淘汰赛。第 i i i 个玩家的胜率用 A i A_i Ai 表示,任意两个不同的玩家的胜率是不一样的。两个玩家进行淘汰的时候,淘汰胜率较小的哪个玩家。问最终获得第二名的玩家编号是多少。

样例数据分析

我们使用样例数据 3 3 3 来分析一下,整个淘汰的过程。

第一次

在这里插入图片描述

第二次

在这里插入图片描述

第三次

在这里插入图片描述
这样,我们可以知道第二名的编号为 2 2 2

题目分析

从上面的数据分析可以看到。本题的考点就是一个二叉搜索树,因此最简单的方法就是使用递归来实现。这里我用数组来实现,这样能更好的理解整个数据变化过程。
有几个二叉树的基本性质需要了解。
1、当前节点编号为 i i i,其父节点编号为 i 2 \frac{i}{2} 2i
2、当前节点编号为 i i i,其右兄弟节点编号为 i + 1 i+1 i+1
这样,我们通过控制数组下标,来实现样例数据分析的过程。

如何记录索引

我们使用结构体。结构体定义如下。

typedef struct _DATA {
    int value;
    int idx;
} DATA;

数据范围分析

注意,本题定义的数组大小为 2 N 2^N 2N。因此 N N N 的最大值为 16 16 16,数组最大为 65536 65536 65536
数据的最大值为 1 0 9 10^9 109,因此用 int 可以。

AC 代码

//https://atcoder.jp/contests/abc188/tasks/abc188_a
//A - Three-Point Shot
#include <bits/stdc++.h>

using namespace std;

//如果提交到OJ,不要定义 __LOCAL
//#define __LOCAL

const int MAXN = 65538;
typedef struct _DATA {
    int value;
    int idx;
} DATA;
DATA a[MAXN];

int main() {
#ifndef __LOCAL
    //这部分代码需要提交到OJ,本地调试不使用
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    int n;
    cin>>n;
    n=pow(2, n);
    for (int i=1; i<=n; i++) {
        cin>>a[i].value;
        a[i].idx = i;
    }

    while (n>2) {
        for (int i=1; i<=n; i+=2) {
            if (a[i].value<a[i+1].value) {
                a[i/2+1].value = a[i+1].value;
                a[i/2+1].idx   = a[i+1].idx;
            } else {
                a[i/2+1].value = a[i].value;
                a[i/2+1].idx   = a[i].idx;
            }
        }
        n/=2;
    }

    if (a[1].value>a[2].value) {
        cout<<a[2].idx<<"\n";
    } else {
        cout<<a[1].idx<<"\n";
    }

#ifdef __LOCAL
    //这部分代码不需要提交到OJ,本地调试使用
    system("pause");
#endif
    return 0;
}

在这里插入图片描述

时间复杂度

O ( l o g 2 N ) O(log{2^N}) O(log2N)

空间复杂度

O(N)。

递归实现

使用完全二叉树的基本定义,我们可以实现递归。

//https://atcoder.jp/contests/abc188/tasks/abc188_a
//A - Three-Point Shot
#include <bits/stdc++.h>

using namespace std;

//如果提交到OJ,不要定义 __LOCAL
//#define __LOCAL

const int MAXN = 65538;
int a[MAXN];
int n;

int solve(int l, int r) {
    //出口
    if (l+1==r) {
        return a[l]>a[r]?l:r;
    }
    //递归
    int mid = (l+r)/2;
    int x=solve(l, mid);
    int y=solve(mid+1, r);
    if (l==1 && r==n) {
        cout<<(a[x]>a[y]?y:x)<<"\n";
        return 0;
    } else {
        return a[x]>a[y]?x:y;
    }
}

int main() {
#ifndef __LOCAL
    //这部分代码需要提交到OJ,本地调试不使用
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cin>>n;
    //n=1<<n;
    n=pow(2, n);
    for (int i=1; i<=n; i++) {
        cin>>a[i];
    }

    if (2==n) {
        cout<<(a[1]>a[2]?'2':'1')<<'\n';
        return 0;
    }
    solve(1, n);

#ifdef __LOCAL
    //这部分代码不需要提交到OJ,本地调试使用
    system("pause");
#endif
    return 0;
}

在这里插入图片描述没有我想象中好。递归只是代码简洁。

时间复杂度

O ( l o g 2 N ) O(log{2^N}) O(log2N)

空间复杂度

O(N)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值