zoukankan      html  css  js  c++  java
  • Bzoj3227 [Sdoi2008]红黑树(tree)

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 204  Solved: 125

    Description

      红黑树是一类特殊的二叉搜索树,其中每个结点被染成红色或黑色。若将二叉搜索树结点中的空指针看作是指向一个空结点,则称这类空结点为二叉搜索树的前端结点。并规定所有前端结点的高度为-1。
      一棵红黑树是满足下面“红黑性质”的染色二叉搜索树:
      (1) 每个结点被染成红色或黑色;
      (2) 每个前端结点为黑色结点;
      (3) 任一红结点的子结点均为黑结点;
      (4) 在从任一结点到其子孙前端结点的所有路径上具有相同的黑结点数。
      从红黑树中任一结点x出发(不包括结点x),到达一个前端结点的任意一条路径上的黑结点个数称为结点x的黑高度,记作bh(x)。红黑树的黑高度定义为其根结点的黑高度。
      给定正整数N,试设计一个算法,计算出在所有含有N个结点的红黑树中,红色内结点个数的最小值和最大值。
     

    Input

      输入共一个数N。
     

    Output

     
      输出共两行。
      第一行为红色内结点个数的最小值,第二行为最大值。
     

    Sample Input


    8

    Sample Output


    1
    4

    HINT

    对于 100% 的数据,1≤N≤5000

    Source

    名叫红黑树的DP题……

    让我想起了之前的名叫最大流的树剖题2333

    动规/贪心

    脑补了一阵子,觉得是树规或者区间DP,然而都好麻烦

    这时旁边神奇的licone说可以贪心 http://blog.csdn.net/senyelicone/article/details/59058778

    -----

    如果树形DP的话,设f[非前端结点数][黑高度][当前结点是红色/黑色]=最大/最小红结点数

    如果区间DP的话,设f[左端点][右端点][当前结点状态]=最大/最小红结点数  ←只是一个想法,目测就算正确也T得飞起

    -----

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 using namespace std;
     9 int main(){
    10     int i,j,n,m;
    11     scanf("%d",&n);
    12     m=n+1;
    13     int ans=0;
    14     while(m>1){
    15         if(m&1)ans++;
    16         m>>=1;
    17     }
    18     printf("%d
    ",ans);//mini
    19     m=n+1;
    20     ans=0;
    21     while(m>1){
    22         if(m==2)ans++;
    23         if(m&3){
    24             if((m&3)==1){
    25                 ans+=m/4*2-1;
    26                 m/=4;m++;
    27             }
    28             else if((m&3)==2){
    29                 ans+=m/4*2;
    30                 m/=4;m++;
    31             }
    32             else if((m&3)==3){
    33                 ans+=m/4*2+1;
    34                 m/=4;m++;
    35             }
    36         }
    37         else{
    38             ans+=m/4*2;
    39             m/=4;
    40         }
    41     }
    42     printf("%d
    ",ans);//max
    43     return 0;
    44 }
    本文为博主原创文章,转载请注明出处。
  • 相关阅读:
    IDEA生成可执行的jar文件
    Android ROM包定制(解包,增删模块,打包)
    frida的用法--Hook Java代码篇
    C语言sprintf和sscanf函数用法
    C语言memcpy函数的用法
    自己动手编译Android(LineageOS)源码
    j2ee高级开发技术课程第三周
    linux内核学习之全局描述符表(GDT)(二)
    螺旋队列顺时针方向 和逆时针方向的实现
    zigzag数组:输入n,求一个nXn矩阵,规定矩阵沿45度递增,形成一个zigzag数组
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6485811.html
Copyright © 2011-2022 走看看