• poj 2892 Tunnel Warfare(线段树)


    题意:有N个点是连通的,现在给出Q个操作,D是破坏这个点,R是恢复最近被破坏的点,Q是询问与这个点相连的点的个数。

    思路:这题与上次比赛的最后一题有点相似,比赛的题是让求从该点往后的相同的字符的个数,而这题是求与这个点相连的点,包括前后。其实线段树也很好理解,节点设四个标记,最左端点,最右端点,从左端点开始,与左端点相连的点的个数,从右端点开始,与右端点相连的点的个数,随时更新,查询时是,先找到最左端相连的区间,然后不断向右找到不相连的点。

    呃, 还是看代码吧。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #define  N 50005
    using namespace std ;
    
    struct node
    {
        int ll , rr ;
        int lval , rval ;//左右相连的点的个数
    }p[4*N] ;
    
    int vis[N] ;
    int n , m ;
    stack<int>st;//栈,用来存放破坏的点
    
    //建树
    void make_tree( int id , int l , int r )
    {
        p[id].ll = l ;
        p[id].rr = r ;
        p[id].lval = p[id].rval = ( r - l + 1 );
        if ( l == r )
        return ;
        int mid = ( l + r )/2 ;
        make_tree( 2*id , l , mid );
        make_tree( 2*id+1 , mid + 1 , r );
    }
    
    //更新
    void update( int id , int num , int flag )
    {
        if( p[id].ll == p[id].rr )
        {
            p[id].lval = p[id].rval = flag ;
            vis[p[id].ll] = flag ;
            return ;
        }
        int mid = ( p[id].ll + p[id].rr ) / 2 ;
        if ( num <= mid )
        update( 2*id , num , flag );
        else
        update( 2*id+1 , num , flag );
    
        p[id].lval = p[2*id].lval ;
        p[id].rval = p[2*id+1].rval ;
        
        //如果左子树的最右边的点和右子树的最左端的点是相连的,那么他们的父节点的左边相连的
        //点的个数要用左子树右边相连点的数加上右子树左边相连点个数。
        if( p[2*id].rval == ( p[2*id].rr - p[2*id].ll + 1))
        p[id].lval += p[2*id+1].lval ;
        //同上
        if( p[2*id+1].rval == ( p[2*id+1].rr - p[2*id+1].ll + 1 ))
        p[id].rval += p[2*id].rval ;
    }
    
    int query( int id , int num )
    {
        if ( p[id].rval == ( p[id].rr - p[id].ll + 1 ))
        {
            return ( p[id].rr - p[id].ll + 1 );
        }
        int mid = ( p[id].ll + p[id].rr ) / 2 ;
        if ( num <= mid )
        {
            if ( p[2*id].rval >= p[2*id].rr - num +1 )
            return query( 2*id , num ) + p[2*id+1].lval ;
            else
            return query( 2*id , num );
        }
        else
        {
            //同上,如果父节点的左端相连的点不止包含在右子树中,还包含在左子树中,那么
            //加上左子树的右端的相连点的个数
            if( p[2*id+1].lval >= num - p[2*id+1].ll + 1 )
            return query( 2*id+1 , num ) + p[2*id].rval ;
            else
            return query( 2*id +1 , num );
        }
    }
    
    int main()
    {
        int i , x ;
        char c ;
        scanf( "%d%d" , &n , &m );
        {
            fill( vis , vis + n + 1 , 1 );
            make_tree( 1 , 1 , n );
            //st.clear();
            while( m-- )
            {
                getchar();
                scanf( "%c" , &c );
                if ( c == 'D' )
                {
                    scanf( "%d" , &x );
                    st.push( x );
                    //st.pop();
                    update( 1 , x , 0 );
                }
                else if ( c == 'R' )
                {
                    x = st.top();
                    st.pop();
                    update( 1 , x , 1 );
                }
                else
                {
                    scanf( "%d" , &x );
                    //查询时,如果该点已经被破坏掉,那么直接输出0
                    if ( !vis[x] )
                    printf ( "0\n" );
                    else
                    printf ( "%d\n" , query( 1 , x ));
                }
            }
        }
        return 0 ;
    }
  • 相关阅读:
    HDFS Maintenance State
    HDFS Maintenance State
    HDFS“慢节点”监控分析功能
    Confluence 6 找到你的支持识别代码(SEN)
    Confluence 6 降级你的许可证
    Confluence 6 增加和减少你许可证的用户数
    Confluence 6 理解你许可证的用户数
    Confluence 6 升级你的许可证
    Confluence 6 查看你的许可证细节
    Confluence 6 管理你的 Confluence 许可证
  • 原文地址:https://www.cnblogs.com/misty1/p/2625277.html
Copyright © 2020-2023  润新知