版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/82228920
这题有点像给出中序遍历和后序遍历求树的结构这样的题,就是分段去递归
考场上没有A掉,算法上出现了一些小错误。
我们对递归的la,ra,lb,rb表示这两段在原树上是同一段,然后记录一个root,表示当前子树中最深的一个可以当根节点在a数组中的下标是多少,然后从前往后扫,如果有不一样的,那么这两个点一点连上当前的root,注意如果当前的root已经有2个儿子了,那么root=fa[a[root]]。
考场上我以为出现了不同的之后,不同之后的那段都在同一棵子树上,其实不然,需要继续往后扫,然后root不断向上
if(la+i+len<=ra)
{
fa[a[la+i+len]]=fa[a[la+i-1]];
find(la+i+len,ra,lb+i+len,rb);
}
break;
#include<cstdio>
#include<cstring>
#define maxl 100010
int n,cas,T;
int a[maxl],b[maxl],dya[maxl],dyb[maxl];
int son[maxl],fa[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),dya[a[i]]=i,fa[i]=0;
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),dyb[b[i]]=i,son[i]=0;
}
void find(int la,int ra,int lb,int rb)
{
int len,idxa,idxb,lla,rra,llb,rrb,root=la;
if(la>=ra || lb>=rb)
return;
for(int i=1;i<ra-la+1;i++)
{
if(a[la+i]!=b[lb+i])
{
while(son[root]==2)
root=fa[a[root]];
idxa=dya[b[lb+i]];
idxb=dyb[a[la+i]];
fa[a[la+i]]=root;
fa[b[lb+i]]=root;
son[root]+=2;
len=idxa-(la+i);
lla=la+i;rra=idxa-1;
llb=idxb;rrb=idxb+len-1;
find(lla,rra,llb,rrb);
len=idxb-(lb+i);
lla=idxa;rra=idxa+len-1;
llb=lb+i;rrb=idxb-1;
find(lla,rra,llb,rrb);
len=idxa-(la+i)+idxb-(lb+i);
i=i+len-1;
}
else
{
while(son[root]==2)
root=fa[a[root]];
fa[a[la+i]]=root,son[root]++;
root=la+i;
}
}
}
inline void mainwork()
{
find(1,n,1,n);
}
inline void print()
{
printf("%d",a[fa[1]]);
for(int i=2;i<=n;i++)
{
printf(" %d",a[fa[i]]);
}
if(cas!=T)
puts("");
}
int main()
{
scanf("%d",&T);
for(cas=1;cas<=T;cas++)
{
prework();
mainwork();
print();
}
return 0;
}