ZOJ 3965

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/82228920
ZOJ