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;
}