蓝桥杯-第九届决赛——版本分支
题目链接 http://oj.ecustacm.cn/problem.php?id=1400
查询是自下而上的,所以本质上是如何往上跳的最快。本质上内存够大,树上的每个位置把祖先节点都存一遍就能o1查询了,但是内存不够,所以需要加速这个跳跃查询。
根据自底向上的特性 所以只需要记录2的幂次方的跳跃。
比如 1 2 3 4 5 6 7 8 9 10
n 存{ 1 , 2 , 4 , 8 … }。可以向上跳的距离记录。
10 存 { 1 ,2 , 4 , 8 }
9 存 { 1 , 2 , 4 , 8 }
8 存 { 1 , 2 , 4 , 8}
7 存 { 1 , 2 , 4 }
…
这样 每个数字最多村log(n)个数字 就能塞下了 ,然后最多向上跳log(n)次就可以向上跳到任何位置
然后 就是向上跳跃,
例如:
比如10 需要寻找7,需要向上跳三次 ,就从10号位置先向上跳两次,再从8号位置向上跳一次,总共跳三次
例如:10 跳到3 ,先向上跳4次到6,然后6向上跳两次到4 , 4 向上跳一次到3 。
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char ch = getchar();
int x = 0, f = 1;
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef vector<int> VI;
typedef vector<VI> VVI;
struct node {
pair<int, int> fa_vec[20]; // 半程二分
int pair_size = 0;
int depth_num; // 记录当前深度
} my_node[100005];
/*
预处理
*/
void dfs(vector<VI> &my_tree, int dad, int node, int depth, VI &depth_tag) {
depth_tag[depth] = node;
my_node[node].depth_num = depth;
int tem_depth = depth;
int count = 0;
while (tem_depth) {
my_node[node].fa_vec[count] =
make_pair(depth - tem_depth, depth_tag[depth - tem_depth]);
tem_depth /= 2;
count += 1;
}
my_node[node].pair_size = count;
for (int i = 0; i < my_tree[node].size(); i++) {
dfs(my_tree, node, my_tree[node][i], depth + 1, depth_tag);
}
}
int get_ancestor_node(int node, int ancestor_depth) {
int tem_node = node;
int i = 0;
while (my_node[tem_node].depth_num > ancestor_depth) {
for (; i < my_node[tem_node].pair_size; ++i) {
if (my_node[tem_node].fa_vec[i].first >= ancestor_depth) {
tem_node = my_node[tem_node].fa_vec[i].second;
break;
}
}
}
return tem_node;
}
bool query(int x, int y) {
if (my_node[x].depth_num > my_node[y].depth_num) {
return false;
}
int result_node = get_ancestor_node(y, my_node[x].depth_num);
if (result_node == x) {
return true;
}
return false;
}
void run() {
int n, q;
// scanf("%d %d ", &n, &q);
n = read();
q = read();
VVI my_tree;
VI depth_tag;
for (int i = 0; i <= n; i++) {
my_tree.push_back(VI());
depth_tag.push_back(-1);
}
int x, y;
for (int i = 0; i < n - 1; i++) {
// scanf("%d %d ", &x, &y);
x = read();
y = read();
my_tree[x].push_back(y);
}
dfs(my_tree, 0, 1, 1, depth_tag);
for (int i = 0; i < q; i++) {
// scanf("%d %d ", &x, &y);
x = read();
y = read();
if (query(x, y)) {
printf("YES\n");
} else {
printf("NO\n");
}
}
}
int main() {
#if defined(__APPLE__)
freopen("./slyar.in", "r+", stdin);
freopen("./slyar.out", "w+", stdout);
#endif
run();
}