题解 P6776 【[NOI2020]超现实树】
题意
定义树
定义树
对于若干二叉树组成的集合
题解
此题牛逼!
记
-
-
不存在
T^{\prime} 满足h(T^{\prime})=n 且T^{\prime}\to T 。
比如说,
多手玩几个你会发现属于
现在我们证明这些
很明显,上面那棵树中有链
同时可以证明
注意到一个性质:对于
不仅如此,还有一个性质是非链树不可以生成链树,因为生成操作不会导致树的基础形态改变。这也就意味着一堆非链树组成的集合一定是不完备的,相当于非链树答案没有影响。依靠这三个性质,我们可以证明只有所有链树是有用的。(也即非链树不能生成链树,而链树可以生成更高的链树从而生成更高的非链树)
现在我们将所有
对于上图链树中的
我们定义四叉树上的节点
这个可以简单搜一下,最后只要看根节点是否是完备的即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e6+51;
ll test,n,m,totn,rt;
ll ls[MAXN],rs[MAXN],c[MAXN],ch[MAXN][4];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll chk(ll x)
{
return !ls[x]&&!rs[x];
}
inline ll check(ll x)
{
if(chk(x)||(!ls[x]&&check(rs[x]))||(!rs[x]&&check(ls[x])))
{
return 1;
}
return (chk(ls[x])&&check(rs[x]))||(chk(rs[x])&&check(ls[x]));
}
inline void merge(ll &cur,ll x)
{
!cur?cur=++totn:1;
if(chk(x))
{
return (void)(c[cur]=1);
}
!rs[x]?merge(ch[cur][0],ls[x]):(void)1;
!ls[x]?merge(ch[cur][1],rs[x]):(void)1;
ls[x]&&rs[x]&&chk(rs[x])?merge(ch[cur][2],ls[x]):(void)1;
ls[x]&&rs[x]&&chk(ls[x])?merge(ch[cur][3],rs[x]):(void)1;
}
inline ll grow(ll x)
{
if(!x||c[x])
{
return !!x;
}
return grow(ch[x][0])&&grow(ch[x][1])&&grow(ch[x][2])&&grow(ch[x][3]);
}
inline void solve()
{
n=read(),rt=totn=0;
for(register int i=1;i<=n;i++)
{
m=read();
for(register int j=1;j<=m;j++)
{
ls[j]=read(),rs[j]=read();
}
check(1)?merge(rt,1):(void)1;
}
puts(grow(1)?"Almost Complete":"No");
for(register int i=1;i<=totn;i++)
{
ch[i][0]=ch[i][1]=ch[i][2]=ch[i][3]=c[i]=0;
}
}
int main()
{
test=read();
for(register int i=0;i<test;i++)
{
solve();
}
}