LCA in a Binary Tree PAT甲级 - 1151

https://pintia.cn/problem-sets/994805342720868352/problems/1038430130011897856

给定前序中序 还原二叉树

用单调栈扫一遍前序 对于一个点 他的父节点的前序肯定小于它 如过栈顶节点的左子树的中序区间包含当前节点 则当前节点为栈顶节点的左孩子 否则是右孩子 或者没有父子关系则pop栈顶

这题有毒啊 给的前序中序不一定是1-n的全排列

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;

struct node
{
    int id,l,r,m,flag;
};

map <int,int> mp1,mp2;
stack <node> stk;
int ch[maxn][2],fa[maxn];
int pre[maxn],mid[maxn],pos[maxn],lef[maxn],rgt[maxn],deep[maxn];
int n,q,num;

int getlca(int u,int v)
{
    if(deep[u]<deep[v]) swap(u,v);
    while(!(lef[u]<=pos[v]&&pos[v]<=rgt[u])) u=fa[u];
    return u;
}

int main()
{
    node cur,tmp;
    int i,u,v,uu,vv,lca;
    scanf("%d%d",&q,&n);
    for(i=1;i<=n;i++){
        scanf("%d",&mid[i]);
        num++;
        mp1[mid[i]]=num,mp2[num]=mid[i];
        pos[num]=i;
    }
    for(i=1;i<=n;i++){
        scanf("%d",&pre[i]);
        pre[i]=mp1[pre[i]];
    }
    tmp.id=pre[1],tmp.l=1,tmp.r=n,tmp.m=pos[pre[1]],tmp.flag=0;
    stk.push(tmp);
    lef[pre[1]]=1,rgt[pre[1]]=n;
    for(i=2;i<=n;i++){
        while(!stk.empty()){
            cur=stk.top();
            stk.pop();
            if(cur.flag==0){
                cur.flag=1;
                if(cur.l<=pos[pre[i]]&&pos[pre[i]]<=cur.m-1){
                    ch[cur.id][0]=pre[i],fa[pre[i]]=cur.id;
                    stk.push(cur);
                    tmp.id=pre[i],tmp.l=cur.l,tmp.r=cur.m-1,tmp.m=pos[pre[i]],tmp.flag=0;
                    stk.push(tmp);
                    lef[pre[i]]=tmp.l,rgt[pre[i]]=tmp.r,deep[pre[i]]=deep[cur.id]+1;
                    break;
                }
            }
            if(cur.flag==1){
                if(cur.m+1<=pos[pre[i]]&&pos[pre[i]]<=cur.r){
                    ch[cur.id][1]=pre[i],fa[pre[i]]=cur.id;
                    tmp.id=pre[i],tmp.l=cur.m+1,tmp.r=cur.r,tmp.m=pos[pre[i]],tmp.flag=0;
                    stk.push(tmp);
                    lef[pre[i]]=tmp.l,rgt[pre[i]]=tmp.r,deep[pre[i]]=deep[cur.id]+1;
                    break;
                }
            }
        }
    }
    while(q--){
        scanf("%d%d",&uu,&vv);
        u=mp1[uu],v=mp1[vv];
        if(!u&&!v) printf("ERROR: %d and %d are not found.\n",uu,vv);
        else if(!u&&v) printf("ERROR: %d is not found.\n",uu);
        else if(u&&!v) printf("ERROR: %d is not found.\n",vv);
        else{
            lca=getlca(u,v);
            if(lca==u) printf("%d is an ancestor of %d.\n",uu,vv);
            else if(lca==v) printf("%d is an ancestor of %d.\n",vv,uu);
            else printf("LCA of %d and %d is %d.\n",uu,vv,mp2[lca]);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值