题目链接:https://pintia.cn/problem-sets/1110382478542622720/problems/1110382589284831244
题目大意:
给定一棵二叉搜索树的先序遍历序列,要求你找出任意两结点的最近公共祖先结点(简称 LCA)。
输入格式:
输入的第一行给出两个正整数:待查询的结点对数 M(≤ 1 000)和二叉搜索树中结点个数 N(≤ 10 000)。随后一行给出 N 个不同的整数,为二叉搜索树的先序遍历序列。最后 M 行,每行给出一对整数键值 U 和 V。所有键值都在整型int范围内。
输出格式:
对每一对给定的 U 和 V,如果找到 A
是它们的最近公共祖先结点的键值,则在一行中输出 LCA of U and V is A.
。但如果 U 和 V 中的一个结点是另一个结点的祖先,则在一行中输出 X is an ancestor of Y.
,其中 X
是那个祖先结点的键值,Y
是另一个键值。如果 二叉搜索树中找不到以 U 或 V 为键值的结点,则输出 ERROR: U is not found.
或者 ERROR: V is not found.
,或者 ERROR: U and V are not found.
。
具体思路:如果是一棵二叉树的先序遍历的话,是建不出树来的,但是这是一颗二叉搜索树,满足左小右大,所以就可以建出树来了。然后建树的时候,保存每个节点的左节点,右节点,父亲节点。判断lca的时候,我们对当前的点往上搜就可以了。
注意离散化的下标。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 const int maxn = 2e4+100; 5 struct node 6 { 7 int lt; 8 int rt; 9 int fa; 10 } q[maxn]; 11 int a[maxn],b[maxn]; 12 void add(int rt,int val) 13 { 14 if(!rt) 15 return ; 16 if(rt>val) 17 { 18 if(q[rt].lt) 19 add(q[rt].lt,val); 20 else 21 { 22 q[rt].lt=val; 23 q[val].fa=rt; 24 return ; 25 } 26 } 27 else 28 { 29 if(q[rt].rt) 30 add(q[rt].rt,val); 31 else 32 { 33 q[rt].rt=val; 34 q[val].fa=rt; 35 return ; 36 } 37 } 38 } 39 int vis[maxn],ans; 40 void Find(int t) 41 { 42 if(!t) 43 return ; 44 if(vis[t]) 45 { 46 ans=t; 47 return ; 48 } 49 vis[t]=1; 50 Find(q[t].fa); 51 } 52 int main() 53 { 54 int n,m; 55 scanf("%d %d",&m,&n); 56 for(int i=0; i<=10000; i++) 57 { 58 q[i].lt=0; 59 q[i].rt=0; 60 q[i].fa=0; 61 } 62 for(int i=1; i<=n; i++) 63 { 64 scanf("%d",&a[i]); 65 b[i]=a[i]; 66 } 67 sort(b+1,b+n+1); 68 int rt; 69 for(int i=1; i<=n; i++) 70 { 71 a[i]=lower_bound(b+1,b+n+1,a[i])-b; 72 if(i==1) 73 rt=a[i]; 74 else 75 add(rt,a[i]); 76 } 77 for(int i=1; i<=m; i++) 78 { 79 int st,ed; 80 scanf("%d %d",&st,&ed); 81 int s1=lower_bound(b+1,b+n+1,st)-b; 82 int s2=lower_bound(b+1,b+n+1,ed)-b; 83 if(b[s1]!=st&&b[s2]!=ed) 84 printf("ERROR: %d and %d are not found. ",st,ed); 85 else if(b[s1]!=st) 86 printf("ERROR: %d is not found. ",st); 87 else if(b[s2]!=ed) 88 printf("ERROR: %d is not found. ",ed); 89 else 90 { 91 Find(s1); 92 if(vis[s2]) 93 printf("%d is an ancestor of %d. ",ed,st); 94 else 95 { 96 Find(s2); 97 if(ans==s1) 98 printf("%d is an ancestor of %d. ",st,ed); 99 else 100 printf("LCA of %d and %d is %d. ",st,ed,b[ans]); 101 } 102 } 103 memset(vis,0,sizeof(vis)); 104 ans=0; 105 } 106 }