• HDU 3887 Counting Offspring (树状数组+人工模拟栈)


    对这棵树DFS遍历一遍,同一节点入栈和出栈之间访问的节点就是这个节点的子树。

    因此节点入栈时求一次 小于 i 的节点个数 和,出栈时求一次 小于 i 的节点个数 和,两次之差就是答案。

    PS.这题直接DFS会爆栈,可以重新设置栈的大小

    #pragma comment(linker,"/STACK:100000000,100000000")

    也可以人工模拟栈,代码如下。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 110000;
    
    struct Edge
    {
        int v;
        int next;
    };
    
    int N, root;
    int EdgeN, top;
    Edge D[ (MAXN << 2) + 100 ];
    int C[ MAXN ];     //树状数组
    int ans[ MAXN ];   //答案
    int pre[ MAXN ];   //入点前的和
    int head[ MAXN ];
    int stack[MAXN];   //手工栈
    bool vis[MAXN];
    
    int lowbit( int x )
    {
        return x&(-x);
    }
    
    int query( int x )
    {
        int res = 0;
        while ( x > 0 )
        {
            res += C[x];
            x -= lowbit(x);
        }
        return res;
    }
    
    void update( int x, int val )
    {
        while ( x <= N )
        {
            C[x] += val;
            x += lowbit(x);
        }
        return;
    }
    
    void AddEdge( int u, int v )
    {
        D[EdgeN].v = v;
        D[EdgeN].next = head[u];
        head[u] = EdgeN++;
        return;
    }
    
    void showStack( int top )
    {
        for ( int i = 1; i <= top; ++i )
            printf( "%d ", stack[i] );
        puts("
    ===================");
        return;
    }
    
    void DFS( int u )
    {
        stack[++top] = u;
        vis[u] = true;
        while ( top )
        {
            int uu = stack[top];
            if ( !vis[uu] ) pre[uu] = query(uu - 1);
            vis[uu] = true;
            int i;
            for ( i = head[uu]; i != -1; i = D[i].next )
            {
                if ( !vis[ D[i].v ] )
                {
                    update( D[i].v, 1 );
                    stack[++top] = D[i].v;
                    //showStack(top);
                    break;
                }
            }
            if ( i == -1 )
            {
                ans[uu] = query( uu - 1 ) - pre[uu];
                --top;
            }
        }
        return;
    }
    
    int main()
    {
        //freopen( "s.txt", "w", stdout );
        while ( scanf( "%d%d", &N, &root ), N || root )
        {
            EdgeN = 1;
            memset( head, -1, sizeof(head) );
            memset( C, 0, sizeof(C) );
    
            for ( int i = 1; i < N; ++i )
            {
                int u, v;
                scanf( "%d%d", &u, &v );
                AddEdge( u, v );
                AddEdge( v, u );
            }
    
            top = 0;
            memset( vis, false, sizeof(vis) );
            memset( pre, 0, sizeof(pre) );
            DFS( root );
    
            printf( "%d", ans[1] );
            for ( int i = 2; i <= N; ++i )
                printf( " %d", ans[i] );
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    四、单片机学习——矩阵键盘实验
    二、单片机学习——独立按键实验
    三、单片机学习——数码管实验(共阳)
    一、单片机学习——流水灯实验
    Cacti监控Linux安装配置snmp服务
    firewalld和iptables区别
    Zabbix图形界面乱码修复为中文显示
    Centos7安装Zabbix 5.0 LTS 版本安装(详细版)
    Ubuntu Server 18.04 网络配置
    linux下开启root用户远程登录,允许无密码登录
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3272050.html
Copyright © 2020-2023  润新知