题意:
给出一颗二叉搜索树的前序遍历,让你还原这棵树,然后给出k次询问,求结点a和b的LCA。
思路:
常规一点的就是建树后记录每个子节点的父亲以及结点的深度,然后普通LCA跑一下,这里不需要倍增,但是也不能分开得两次dfs(因为退化的二叉搜索树只有一条单链的时候,会炸),得先让两个结点跑到同一层,然后再一起去找爸爸,PAT的题所有操作都暴力就行。
这个题写了两个不易察觉的bug:1. 用map映射的时候,我从零开始了,后面还涉及到查找mp[a]。
2. 想当然得与上一次的LCA题一样写了两个dfs,只可惜这次数据没让我过
心得:
评测机这门学问还挺深,用clang++交卡我建树,用g++就过了.....所以当出现觉得自己dfs没问题的时候可以试着换一种语言交。
代码:
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <stack>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N = 1e4+50;
const double eps = 1.e-8;
int n, m, k, cnt, a, b;
struct node {
int left, right;
int val;
int exist;
int cen;
}edge[N];
map<int, int> mp, rmp;
int vis[N], pre[N], U;
void build (int root, int th, int val, int fa, int zy, int cen) {//clang++卡了我2个小时的建树...
if (!edge[root].exist) {
edge[root].val = val;
edge[root].exist = 1;
pre[root] = fa;
edge[root].cen = cen;
if (zy == 1) edge[fa].right = root;
else if (zy == 0) edge[fa].left = root;
return ;
}
if (val < edge[root].val) {
if (edge[root].left != -1) {
build(edge[root].left, th, val, root, 0, cen+1);
}
else {
build(th, th, val, root, 0, cen+1);
}
}
else {
if (edge[root].right != -1) {
build(edge[root].right, th, val, root, 1, cen+1);
}
else {
build(th, th, val, root, 1, cen+1);
}
}
}
void slove(int aa, int bb) {//先跑到同一层再去找爸爸。
int u = mp[aa];
int v = mp[bb];
if (edge[u].cen > edge[v].cen) {
while (edge[u].cen != edge[v].cen) u = pre[u];
while (u != v) {
u = pre[u];
v = pre[v];
}
if (u == mp[bb]) printf("%d is an ancestor of %d.\n", bb, aa);
else printf("LCA of %d and %d is %d.\n", aa, bb, rmp[v]);
}
else {
while (edge[u].cen != edge[v].cen) v = pre[v];
while (u != v) {
u = pre[u];
v = pre[v];
}
if (u == mp[aa]) printf("%d is an ancestor of %d.\n", aa, bb);
else printf("LCA of %d and %d is %d.\n", aa, bb, rmp[v]);
}
}
int main() {
cin>>m>>n;
for (int i = 0; i < N; i++) {
edge[i].left = -1;
edge[i].right = -1;
edge[i].exist = 0;
pre[i] = i;
}
cnt = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &k);
mp[k] = cnt;
rmp[cnt] = k;
cnt++;
build(0, i, k, 0, -1, 0);
}
while (m--) {
scanf("%d%d", &a, &b);
if (!mp.count(a) && !mp.count(b)) printf("ERROR: %d and %d are not found.\n", a, b);
else if (!mp.count(a)) printf("ERROR: %d is not found.\n", a);//注意这里用count查找,因为映射有0.
else if (!mp.count(b)) printf("ERROR: %d is not found.\n", b);
else
slove(a, b);//exist
}
return 0;
}