PAT-2021年秋季考试 - 甲级 7-4 Sorted Cartesian Tree (C++)

A Sorted Cartesian tree is a tree of (key, priority) pairs. The tree is heap-ordered according to the priority values, and an inorder traversal gives the keys in sorted order. For example, given the pairs { (55, 8), (58, 15), (62, 3), (73, 4), (85, 1), (88, 5), (90, 12), (95, 10), (96, 18), (98, 6) }, the increasing min-heap Cartesian tree is shown by the figure.
在这里插入图片描述
Your job is to do level-order traversals on an increasing min-heap Cartesian tree.

Input Specification:

Each input file contains one test case. Each case starts from giving a positive integer N ( ≤ 30 ) N (≤30) N(30), and then N N N lines follow, each gives a pair in the format key priority. All the numbers are in the range of int.

Output Specification:

For each test case, print in the first line the level-order traversal key sequence and then in the next line the level-order traversal priority sequence of the min-heap Cartesian tree.

All the numbers in a line must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.

Sample Input:

10
88 5
58 15
95 10
62 3
55 8
98 6
85 1
90 12
96 18
73 4

Sample Output:

85 62 88 55 73 98 58 95 90 96
1 3 5 8 4 6 15 10 12 18

Caution:

说实话拿到这道题我还是有点怵的,一个是因为这道树的题目竟然放到了第四题的位置,另外一个原因是这个数据结构以前从来没听说过(孤陋寡闻了),并且当时写这道题的时候状态也不是特别好(空调开得太冷了,当时肚子疼了一阵子),不过看清楚题目后规规矩矩写还是一遍 AC 了(虽然代码可能确实有些烂),题目其实不难,主要就是建树的过程和以往不太一样(不过姥姥这么安排确实有点考验心态的意思)。

附上其他三道题的解答:7-17-27-3

Solution:

// Talk is cheap, show me the code
// Created by Misdirection 2021-09-11 14:28:36
// All rights reserved.

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <queue>

using namespace std;

struct Node{
    int key;
    int priority;
    Node *left;
    Node *right;

    Node(int k, int p){
        key = k;
        priority = p;
        left = NULL;
        right = NULL;
    }
    ~Node(){}
};

int n;
vector<Node> nodes;
vector<int> keyLevelOrder, priLevelOrder;
unordered_map<int, int> pri2Pos;
int pri[35];
Node *root;
unordered_map<int, bool> vis;

void findChildren(Node *r, int posInSorted, int leftEdge, int rightEdge){
    if(r == NULL) return;
    
    int left = -1, right = -1;
    for(int i = posInSorted + 1; i < n; ++i){
        if(vis[pri[i]]) continue;

        if(left == -1 && nodes[pri2Pos[pri[i]]].key < r -> key && nodes[pri2Pos[pri[i]]].key > leftEdge){
            left = i;
            vis[pri[i]] = true;
            continue;
        }
        else if(right == -1 && nodes[pri2Pos[pri[i]]].key > r -> key && nodes[pri2Pos[pri[i]]].key < rightEdge){
            right = i;
            vis[pri[i]] = true;
            continue;
        }
    }

    if(left != -1)
        r -> left = new Node(nodes[pri2Pos[pri[left]]].key, nodes[pri2Pos[pri[left]]].priority);
    if(right != -1)
        r -> right = new Node(nodes[pri2Pos[pri[right]]].key, nodes[pri2Pos[pri[right]]].priority);

    findChildren(r -> left, left, leftEdge, r -> key);
    findChildren(r -> right, right, r -> key, rightEdge);
}

int main(){
    scanf("%d", &n);
    
    int k, p;
    for(int i = 0; i < n; ++i){
        scanf("%d %d", &k, &p);
        nodes.emplace_back(k, p);
        pri2Pos[p] = i;
        pri[i] = p;
    }

    sort(pri, pri + n);
    root = new Node(nodes[pri2Pos[pri[0]]].key, pri[0]);

    findChildren(root, 0, -2147483648, 2147483647);

    queue<Node*> q;
    q.push(root);
    while(!q.empty()){
        if(q.front() -> left != NULL) q.push(q.front() -> left);
        if(q.front() -> right != NULL) q.push(q.front() -> right);

        keyLevelOrder.push_back(q.front() -> key);
        priLevelOrder.push_back(q.front() -> priority);
        q.pop();
    }

    for(int i = 0; i < n; ++i){
        if(i == n - 1) printf("%d\n", keyLevelOrder[i]);
        else printf("%d ", keyLevelOrder[i]);
    }
    for(int i = 0; i < n; ++i){
        if(i == n - 1) printf("%d\n", priLevelOrder[i]);
        else printf("%d ", priLevelOrder[i]);
    }

    return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

负反馈循环

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

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

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

打赏作者

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

抵扣说明:

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

余额充值