zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    ZOJ 3529
    将博客搬至CSDN
    BST 增删查操作 递归/非递归实现
    容器vector容量翻倍增长策略效率分析
    整数分解为若干项之和
    PAT-B-1080 MOOC期终成绩
    最大公约数 + 最小公倍数
    Fibonacci数
    排序
    PAT-B-1020
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10613343.html
Copyright © 2011-2022 走看看