1135 Is It A Red-Black Tree (30 分)
\(30\)分的题目果然顶啊。
思路
根据先序中序建立一棵树
- 判断根结点是否是黑色。
- 根据建立的树,从根结点开始遍历,如果当前结点是红色,判断它的孩子节点是否为黑色。
- 从根节点开始,递归遍历,检查每个结点的左子树的高度和右子树的黑色结点的个数,比较个数集合大小是否为\(1\)。
const int N=35;
unordered_map<int,PII> tree;
unordered_map<int,int> pos;
int pre[N],in[N];
int n;
set<int> S;
bool ok;
int build(int prel,int prer,int inl,int inr)
{
if(!ok) return 0;
if(prel > prer) return 0;
int root=pre[prel];
int k=pos[abs(root)];
if(k<inl || k>inr)
{
ok=false;
return 0;
}
int leftlen=k-inl;
int lchild=build(prel+1,prel+leftlen,inl,k-1);
int rchild=build(prel+leftlen+1,prer,k+1,inr);
tree[root]={lchild,rchild};
return root;
}
void dfs(int root,int cnt)
{
if(root == 0)
{
S.insert(cnt);
return;
}
if(root > 0)
{
dfs(tree[root].fi,cnt+1);
dfs(tree[root].se,cnt+1);
}
else
{
dfs(tree[root].fi,cnt);
dfs(tree[root].se,cnt);
}
}
bool check(int root)
{
if(root < 0) return false;
queue<int> q;
q.push(root);
while(q.size())
{
int t=q.front();
q.pop();
S.clear();
dfs(t,0);
if(S.size() > 1) return false;
if(tree[t].fi)
{
if(t < 0 && tree[t].fi < 0) return false;
q.push(tree[t].fi);
}
if(tree[t].se)
{
if(t < 0 && tree[t].se < 0) return false;
q.push(tree[t].se);
}
}
return true;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>pre[i];
in[i]=abs(pre[i]);
}
sort(in,in+n);
for(int i=0;i<n;i++) pos[in[i]]=i;
ok=true;
int root=build(0,n-1,0,n-1);
if(ok) ok=check(root);
if(ok) puts("Yes");
else puts("No");
}
//system("pause");
return 0;
}