1. 程式人生 > >1151 LCA in a Binary Tree(30 分)

1151 LCA in a Binary Tree(30 分)

題目大意:給出中序序列和先序序列,再給出兩個點,求這兩個點的最近公共祖先。

解題思路:不用建樹~已知某個樹的根結點,若a和b在根結點的左邊,則a和b的最近公共祖先在當前子樹根結點的左子樹尋找,如果a和b在當前子樹根結點的兩邊,在當前子樹的根結點就是a和b的最近公共祖先,如果a和b在當前子樹根結點的右邊,則a和b的最近公共祖先就在當前子樹的右子樹尋找。中序加先序可以唯一確定一棵樹,在不構建樹的情況下,在每一層的遞迴中,可以得到樹的根結點,在此時併入lca演算法可以確定兩個結點的公共祖先~

AC 程式碼

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a)
#define ssclr(ss) ss.clear(), ss.str("")
#define INF 0x3f3f3f3f
#define MOD 1000000007

using namespace std;

typedef long long ll;

const int maxn=1e4+10;

int in[maxn], pre[maxn];
unordered_map<int,int> pos;

void lca(int inl,int inr,int prel,int a,int b)
{
    if(inl>inr) return;
    int inRt=pos[pre[prel]], aIn=pos[a], bIn=pos[b];
    if(inRt>aIn && inRt<bIn || inRt<aIn && inRt>bIn) printf("LCA of %d and %d is %d.\n", a, b, in[inRt]);
    else if(aIn==inRt || bIn==inRt) printf("%d is an ancestor of %d.\n", in[inRt], aIn==inRt ? b : a);
    else if(aIn>inRt && bIn>inRt) lca(inRt+1,inr,prel+1+(inRt-inl),a,b);
    else if(aIn<inRt && bIn<inRt) lca(inl,inRt-1,prel+1,a,b);
}

int main()
{
    int q,n,a,b;
    scanf("%d%d",&q,&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]);
    while(q--)
    {
        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;
}