题意:
给定一棵二叉排序树,问任意两个点的 lca 情况
思路:
根据规则建树,结构体存每个结点以及其深度,父亲节点
每次寻找lca的时候,先让待查找点同层次,然后直接暴力往上寻找他们的lca,当找到同一个结点的时候就是lca
ps:时间复杂度飘过,还有倍增lca,预处理每个结点的祖先结点情况,这里就不赘述了。一帮pat的题暴力都ok
#include<bits/stdc++.h>
#include<cstring>
#define FI first
#define SE second
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 1e4 + 7;
const int maxd = 2e4 + 77;
const ll INF = 0x7f7f7f7f;
int m, n;
map<int, int> mp;
struct node {
int v, fa, du;
int l_, r_;
}a[maxn];
void add(int id, int id_, int cnt) {
if(a[id_].v < a[id].v) {
if(a[id].l_) {
add(a[id].l_, id_, cnt+1);
}
else {
a[id].l_ = id_;
a[id_].fa = id;
a[id_].du = cnt+1;
}
}
else {
if(a[id].r_) {
add(a[id].r_, id_, cnt+1);
}
else {
a[id].r_ = id_;
a[id_].fa = id;
a[id_].du = cnt+1;
}
}
}
void init() {
a[1].du = 1;
for(int i = 2; i <= n; ++i) {
add(1, i, 1);
}
}
int lca(int id1, int id2) {
if(id1 == id2) return a[id1].v;
if(a[id1].du > a[id2].du) swap(id1, id2);
int t = a[id2].du - a[id1].du;
while(t--) id2 = a[id2].fa;
while(id1 != id2) id1 = a[id1].fa, id2 = a[id2].fa;
return a[id1].v;
}
void solve() {
int u, v;
for(int i = 1; i <= m; ++i) {
scanf("%d%d", &u, &v);
int t1 = mp[u], t2 = mp[v];
if(!t1 && !t2) {
printf("ERROR: %d and %d are not found.\n", u, v);
}
else if(!t1) {
printf("ERROR: %d is not found.\n", u);
}
else if(!t2) {
printf("ERROR: %d is not found.\n", v);
}
else {
int t = lca(t1, t2);
if(t == u) {
printf("%d is an ancestor of %d.\n", u, v);
}
else if(t == v) {
printf("%d is an ancestor of %d.\n", v, u);
}
else {
printf("LCA of %d and %d is %d.\n", u, v, t);
}
}
}
}
int main() {
scanf("%d%d", &m, &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i].v);
mp[a[i].v] = i;
}
init();
solve();
return 0;
}