A. Almost Balanced Tree(构造)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A. Almost Balanced Tree(构造)相关的知识,希望对你有一定的参考价值。
也可以这样,根据 A + B A+B A+B节点数计算出前 k k k层节点是满的
那么若 B < 2 k − 1 B<2^k-1 B<2k−1,根据二进制的性质,可以从中抽取若干层都放 2 2 2节点
那么剩下的都是 1 1 1节点,就随便构造了
若 B > = 2 k − 1 B>=2^k-1 B>=2k−1,贪心的想,让前 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,b−1)也可以构造出解
因为可以使用两个权值 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