题意:
求一颗(n)个节点的红黑树红色节点数目最多和最少
红黑树是满足如下性质的的染色二叉搜索树:
- 每个结点被染成红色或黑色;
- 每个前端结点为黑色结点;
- 任一红结点的子结点均为黑结点;
- 在从任一结点到其子孙前端结点的所有路径上具有相同的黑结点数。
- 二叉搜索树结点中的空指针看作是指向一个空结点,则称这类空结点为二叉搜索树的前端结点。并规定所有前端结点的高度为 -1。
范围&性质:(1le nle 5000)
分析:
- 贪心
首先对于一颗(n)个点的红黑树,他必定存在且仅存在(n+1)个前端节点,我们构造红黑树的过程可以看做,用这(n+1)个前端节点反向递推到根节点的过程
由于前端节点的颜色全是黑色,所以我们考虑一堆黑色的叶子结点向上递推的过程,由上面的性质3,4我们可以推出以下几种情况:
- 两个黑点变成一个黑点
- 三个黑点变成一个红点一个黑点
- 四个黑点变成一个黑点和两个红点
- 五个黑点变成两个黑点一个红点
这里有一张图,其中最下面一层黑色节点可以看做是前端节点(来源网上,侵删)
对于红色节点最少的情况我们按照两个黑点一组的情况去反向递推,这样每次操作得到的红色节点最少
对于红色节点最多的情况我们按照四个黑点一组的情况去合并,这样每次操作得到的红色节点最多
- 动态规划(以后填坑,
下次一定)
代码:
- 贪心:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
int n,ans,m;
void work()
{
scanf("%d",&n);
m=n+1;
while(m>1)
{
ans+=m&1;
m>>=1;
}
printf("%d
",ans);
m=n+1;ans=0;
while(m>1)
{
if(m==2) ans++,m--;
else if((m&3)==1) ans+=((m>>2)<<1)-1,m>>=2,m++;
else if((m&3)==2) ans+=((m>>2)<<1),m>>=2,m++;
else if((m&3)==3) ans+=((m>>2)<<1)+1,m>>=2,m++;
else ans+=(m>>1),m>>=2;
}
printf("%d
",ans);
}
}
int main()
{
zzc::work();
return 0;
}