缺损二叉树


题目

by 庾湫镆

描述

有一棵满二叉树, 按层序依次编号为 1 .... 现指定一部分编号, 当层序遍历到这些编号时, 它们的子孙结点将不会加入遍历. 在这种情况下, 求从根节点到目标编号结点的路径.

IO格式

输入:

指定编号数 目标编号数
指定编号...     // 从小到大
目标编号...     // 从小到大

输出:

路径
...

样例

输入:

3 4
5 6 9
3 9 15 22

输出:

1 3 
1 2 4 9 
1 3 7 10 15 
1 3 7 10 14 22

解答

思路

当一个结点前面出现了 absentNum 个指定编号结点的子树, 它与其父节点之间的编号关系 (father = son >> 1) 将会偏移 absentNum. 只要我们求出 absentNum 对应的结点编号区间 absentRanges[absentNum], 就能轻松解决这道题.

代码

#include <array>
#include <cstdio>
#include <stack>
using namespace std;

#define prf printf
#define scf scanf
using ui = unsigned long long;

ui N;                            // 缺损点数目
ui M;                            // 目标点数目
array<ui, 102> absentNodes;      // 缺损点, [0]空余
array<ui, 102> absentRanges{1};  // 缺损连续区间, 0表示不存在

ui findLeftSon(ui father, ui absentNum) { return (father - absentNum) << 1; }

ui findFather(ui son, ui absentNum) { return (son >> 1) + absentNum; }

ui findRange(ui target) {
    for (auto i = N; i >= 0; i--)
        if (absentRanges[i] != 0)
            if (absentRanges[i] <= target) return i;
}

int main() {
    scf("%u%u", &N, &M);
    for (auto i = 1; i <= N; i++) {
        ui temp;
        scf("%u", &temp);
        absentNodes[i] = temp;
        absentRanges[i] = findLeftSon(temp, i - 1);
        if (absentRanges[i] == absentRanges[i - 1]) absentRanges[i - 1] = 0;
    }
    for (auto i = 0; i < M; i++) {
        ui temp;
        scf("%u", &temp);
        stack<ui> path;
        path.push(temp);
        ui pathLen = 1;
        auto flag = false;
        while (temp != 1) {
            auto tempFather = findFather(temp, findRange(temp));
            if (tempFather >= temp) {
                flag = true;
                break;
            }
            temp = tempFather;
            path.push(temp);
            pathLen++;
        }
        if (flag) {
            prf("0\n");
            continue;
        } else {
            for (auto j = 0; j < pathLen; j++) {
                prf("%u ", path.top());
                path.pop();
            };
            prf("\n");
        }
    }
    return 0;
}

时空消耗

1	Accepted	0 ms	920 KB
2	Accepted	0 ms	916 KB
3	Accepted	0 ms	924 KB
4	Accepted	0 ms	916 KB
5	Accepted	0 ms	916 KB
6	Accepted	0 ms	920 KB
7	Accepted	0 ms	916 KB
8	Accepted	0 ms	916 KB
9	Accepted	0 ms	924 KB
10	Accepted	0 ms	920 KB