7-14 二叉搜索树的最近公共祖先 (30 分)

题目链接: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 }
原文地址:https://www.cnblogs.com/letlifestop/p/10613343.html