題目鏈接:https://pintia.cn/problem-sets/994805342720868352/problems/1038430130011897856
題目大意:給定中序和先序,求給定兩個點的最近公共祖先。
分析:假設給出的是a和b,若a和b在當前根節點的左子樹上,那麼就在當前根節點的左子樹上找,同理,都在右子樹上,就在當前根節點的右子樹上找,如果一個左邊,一個右邊,那麼答案就是當前根節點。
14行:inroot - l是左子樹的節點數,所以先序數組肯定往右移動inroot - l,然後再加上當前根節點,所以再加1。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
int n, m, in[N], pre[N];
map<int, int> pos;
void lca(int l, int r, int preroot, int a, int b) {
if(l > r) return ;
int inroot = pos[pre[preroot]], ain = pos[a], bin = pos[b];
if(ain < inroot && bin < inroot) {
lca(l, inroot - 1, preroot + 1, a, b);
} else if((ain < inroot && bin > inroot) || (ain > inroot && bin < inroot)) {
printf("LCA of %d and %d is %d.\n", a, b, in[inroot]);
} else if(ain > inroot && bin > inroot) {
lca(inroot + 1, r, preroot + 1 + inroot - l, a, b);
} else if(ain == inroot) {
printf("%d is an ancestor of %d.\n", a, b);
} else if(bin == inroot) {
printf("%d is an ancestor of %d.\n", b, a);
}
}
int main() {
scanf("%d %d", &m, &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &in[i]);
pos[in[i]] = i;
}
for(int i = 1; i <= n; i++)
scanf("%d", &pre[i]);
int a, b;
while(m--) {
scanf("%d %d", &a, &b);
if(pos[a] == 0 && pos[b] == 0) {
printf("ERROR: %d and %d are not found.\n", a, b);
} else if(pos[a] == 0 || pos[b] == 0) {
printf("ERROR: %d is not found.\n", pos[a] == 0 ? a : b);
} else {
lca(1, n, 1, a, b);
}
}
return 0;
}