A. Almost Balanced Tree(构造)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A. Almost Balanced Tree(构造)相关的知识,希望对你有一定的参考价值。

LINK

也可以这样,根据 A + B A+B A+B节点数计算出前 k k k层节点是满的

那么若 B < 2 k − 1 B<2^k-1 B<2k1,根据二进制的性质,可以从中抽取若干层都放 2 2 2节点

那么剩下的都是 1 1 1节点,就随便构造了

B > = 2 k − 1 B>=2^k-1 B>=2k1,贪心的想,让前 k k k层全部放 2 2 2节点

然后把剩余的 A , B A,B A,B节点从根节点递归下去,每次都二分

到了第 k + 1 k+1 k+1层就可以开始构造了

(当然还是有小概率凑不成,再 d f s dfs dfs验证一遍即可)

#include <iostream>
using namespace std;
const int maxn = 1e6+10;
int A,B,ok[55],flag,k,id;
int val[maxn],ls[maxn],rs[maxn];
int flag1,flag2,mx1,mx2;
void dfs(int u,int fa,int deep,int suma,int sumb)
{
	if( ok[deep] || flag )	val[u] = 2;
	else	val[u] = 1;	

	if( deep+1==k )
	{
		if( sumb )	rs[u] = ++id, val[id] = 2;
		if( suma )	ls[u] = ++id, val[id] = 1;
		if( suma==2 && sumb )	ls[id] = id+1, ++id, val[id] = 1;
		if( suma==2 && !sumb )	rs[u] = ++id, val[id] = 1;
		return;
	}	
	ls[u] = u<<1; rs[u] = u<<1|1;
	dfs( ls[u], u , deep+1, suma/2, sumb/2 );
	dfs( rs[u], u , deep+1, suma-suma/2, sumb-sumb/2 );
}
int sum[maxn];
void DP(int u)
{
	if( !u )	return;
	DP( ls[u] ); DP( rs[u] );
	if( abs( sum[ls[u]]-sum[rs[u]] )>1 )	{ cout << -1; exit(0); }
	sum[u] = sum[ls[u]]+sum[rs[u]]+val[u];
}
int main()
{
	cin >> A >> B;
	for(int i=0;i<=20;i++)
	{
		if( (B>>i)&1 )	ok[i] = 1;
		if( (1<<i)-1<=A+B )	k = i;
	}
	if( (1<<k)-1<B )	B -= (1<<k)-1,flag = 1;
	else	A -= (1<<k)-1-B, B = 0;
	if( A<B ){ cout << -1; return 0; }
	
	id = (1<<k)-1;
	dfs(1,1,0,A,B); DP(1);
	for(int i=1;i<=id;i++)
		cout << val[i] << " " << ls[i] << " " << rs[i] << endl;
}

如果权值只有 1 1 1,那么很容易可以构造答案

如果权值只有 2 2 2,那么几乎不可能构造出答案(除非完全铺满二叉树的每一层)

进一步发现,如果 ( a , b ) (a,b) (a,b)可以构造出解,那么 ( a + 2 , b − 1 ) (a+2,b-1) (a+2,b1)也可以构造出解

因为可以使用两个权值 1 1 1代替掉那个权值为 2 2 2的节点

如果无法构造解,一定是因为奇数个 2 2 2无法平均分配给两个儿子,又没有足够的 1 1 1来平衡他们

所以当权值为 2 2 2的节点为奇数个时,我们在根节点放权值 2 2 2的节点

然后平均分配给子树

权值为 1 1 1的节点再去填充剩余的空节点,有多余再同样二分

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+19;
int val[maxn],vis[maxn];
void dfs1(int u,int B)
{
	if( !B )	return;
	vis[u] = 1;
	if( B&1 )	val[u] = 2,B--;
	dfs1( u<<1,B/2 ),dfs1( u<<1|1,B/2 );
}
void dfs2(int u,int& A)
{
	if( !val[u] )	val[u] = 1, A--; 
	if( vis[u<<1] )	dfs2( u<<1,A );
	if( vis[u<<1|1] )	dfs2( u<<1|1,A );
}
void dfs3(int u,int A)
{
	if( !val[u] && A )	val[u] = 1, A--;
	if( A )
		dfs3( u<<1,A/2 ),dfs3( u<<1|1,A-A/2 );
}
int id,ID[maxn],top[maxn];
void dfs4(int u)
{
	if( !val[u] )	return;
	top[++id] = u;	ID[u] = id;
	dfs4( u<<1 ); dfs4( u<<1|1 );
}
int main()
{
	int A,B; scanf("%d%d",&A,&B );
	dfs1( 1,B ); 
	dfs2( 1,A );
	if( A<0 )	cout << -1;
	else
	{
		dfs3(1,A);
		dfs4(1);
		for(int i=1;i<=id;i++)
		{
			int u = top[i];
			printf("%d %d %d\\n",val[u],ID[u<<1],ID[u<<1|1] );
		}
	}
}

以上是关于A. Almost Balanced Tree(构造)的主要内容,如果未能解决你的问题,请参考以下文章

[Leetcode] Balanced Binary Tree

LC.110. Balanced Binary Tree

Problem A. Balanced Fighters

Leetcode[110]-Balanced Binary Tree

110. Balanced Binary Tree

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树