[补题记录] Atcoder Beginner Contest 321(E)

URL:https://atcoder.jp/contests/abc321

目录

E

Problem/题意

Thought/思路

Code/代码


E

Problem/题意

有一颗 N 个节点的完全二叉树,现在给出节点 X,一个整数 K,问举例节点 X 的长度为 K 的点有多少个?

Thought/思路

来自:https://www.cnblogs.com/Lanly/p/17725350.html

首先考虑以节点 X 为根的子树,求出往下 K 层的左端点和右端点,再与 N 比较大小即可求出这颗子树的答案;

其次考虑与 X 同一个父亲的节点,按照前面求子树的方法求它的答案;

不断往 X 的父节点考虑,求与 X 对称的点的子树答案,直到 X = 1 或者 K == 0,此时若 K == 0,则说明当前的 X 作为单独一个点的答案。

[补题记录] Atcoder Beginner Contest 321(E)_第1张图片

Code/代码

 

#include "bits/stdc++.h"

#define int long long

__int128 n;

__int128 solve(__int128 x, __int128 k) { // 处理以 x 为根的子树
	if (k > 64 or k < 0) return 0;

	__int128 len = (1ll << k), l = (x << k);
	__int128 r = l + len - 1;

	if (l > n) return 0;
	if (r > n) {
		return n - l + 1;
	} else {
		return r - l + 1;
	}
}

__int128 read() {
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

void print(__int128 x) {
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

signed main() {
	int t; std::cin >> t;
	while (t --) {
		__int128 x , k;
		n = read();x = read();k = read();
		
		int ans = 0;
		// 先求 x 的子树
		if (k) ans += solve(x, k);
		// 不断求 x 的父节点的另一个节点,即另一颗子树
		while (x > 1 and k > 0) {
			k -= 1; // 往上一层
			ans += solve((x ^ 1), k - 1); // 以 x 的父节点的另一个节点为根的子树
			x /= 2;
		}
		// 某个父节点时 k == 0
		if (x and k == 0) ans ++;

		print(ans);
		std::cout << "\n";
	}
}

你可能感兴趣的:(补题记录,算法,图论)