zoukankan      html  css  js  c++  java
  • bzoj1036 树的统计Count

    第一次写链剖,于是挑了个简单的裸题写。

    以下几点要注意:

    1.链剖中的height是从根到该店经过的轻边个数

    2.分清num与sum。。。。。

    #include<cstdio>
    #include<algorithm>
    using namespace std ; 
     
    const int MAXN = 3 * 10000 + 20 ;  
    const int MAX_SIZE = 32 * 1024 + 1 ;
    int N , Q ; 
    
    int max_equal ( int & a , const int b ) { if ( a < b ) a = b ; return a ; }
    
    namespace Seg {
    
    int maxv [ MAX_SIZE * 2 ] ; 
    int sumv [ MAX_SIZE * 2 ] ; 
    int value [ MAXN ] ; 
    int l , r , v ; 
    
    void maintain ( const int o ) {
        const register int o1 = o << 1 , o2 = o << 1 | 1 ; 
        maxv [ o ] = max ( maxv [ o1 ] , maxv [ o2 ] ) ;
        sumv [ o ] = sumv [ o1 ] + sumv [ o2 ] ;
    }
    
    void __build ( const int o , const int L , const int R ) {
        if ( R - L == 1 ) maxv [ o ] = sumv [ o ] = value [ L ] ; 
        else {
            const int M = ( L + R ) / 2 ; 
            __build ( o << 1 , L , M ) ;
            __build ( o << 1 | 1 , M , R ) ; 
            maintain ( o ) ; 
        }
    }
    void build () {
        __build ( 1 , 0 , N ) ; 
    }
    
    void _modify ( const int o , const int L , const int R ) {
        if ( R - L == 1 ) maxv [ o ] = sumv [ o ] = v ; 
        else {
            const int M = ( L + R ) / 2 ; 
            if ( l < M ) _modify ( o << 1 , L , M ) ;
            else _modify ( o << 1 | 1 , M , R ) ; 
            maintain ( o ) ;
        }
    }
    void modify ( const int p , const int V ) {
        l = p ; v = V ; _modify ( 1 , 0 , N ) ; 
    }
    
    void _Qmax ( const int o , const int L , const int R ) {
        if ( l <= L && R <= r ) max_equal ( v , maxv [ o ] ) ;
        else {
            const int M = ( L + R ) / 2 ; 
            if ( l < M ) _Qmax ( o << 1 , L , M ) ;
            if ( M < r ) _Qmax ( o << 1 | 1 , M , R ) ;
        }
    }
    int Qmax ( int L , int R ) {
        if ( L > R ) swap ( L , R ) ;
        l = L ; r = R + 1 ; v = - ( 1 << 30 ) /* -INF */ ;
        _Qmax ( 1 , 0 , N ) ;
        return v ; 
    }
    
    void _Qsum ( const int o , const int L , const int R ) {
        if ( l <= L && R <= r ) v += sumv [ o ] ; 
        else {
            const int M = ( L + R ) / 2 ; 
            if ( l < M ) _Qsum ( o << 1 , L , M ) ;
            if ( M < r ) _Qsum ( o << 1 | 1 , M , R ) ;
        }
    }
    int Qsum ( int L , int R ) {
        if ( L > R ) swap ( L , R ) ;
        l = L ; r = R + 1 ; v = 0 ;
        _Qsum ( 1 , 0 , N ) ;
        return v ; 
    }
    
    }
    
    struct edge {
        int p ; 
        edge * nxt ; 
    } ;
    edge * V [ MAXN ] ;
    int value [ MAXN ] ; 
    edge E [ MAXN * 2 ] ; 
    
    void ___add_edge ( const int a , const int b ) {
        static edge * t = E ; 
        t -> p = b ; t -> nxt = V [ a ] ; V [ a ] = t ++ ; 
    }
    void add_edge ( const int a , const int b ) {
        ___add_edge ( a , b ) ;
        ___add_edge ( b , a ) ;
    }
    
    namespace Link_cut {
    
        int top [ MAXN ] ;
        int num [ MAXN ] ;
        int size [ MAXN ] ; 
        int height [ MAXN ] ; 
        int father [ MAXN ] ;
    
        namespace GET_SIZE {
            int dfs ( const int o ) {
                size [ o ] = 1 ; 
                for ( edge * i = V [ o ] ; i != 0 ; i = i -> nxt ) 
                if ( i -> p != father [ o ] ) {
                    father [ i -> p ] = o ; 
                    size [ o ] += dfs ( i -> p ) ;
                }
                return size [ o ] ;
            }
        }
        void Get_size () { father [ 0 ] = 0 ; GET_SIZE :: dfs ( 0 ) ; }  
        
        namespace LINK_CUT {
            void dfs ( const int o , const int t , const int h ) {
                if ( o < 0 ) return ;
                else {
                    static int dfs_clock = 0 ; 
                    top [ o ] = t ; 
                    num [ o ] = dfs_clock ++ ; 
                    height [ o ] = h ; 
                    int max_size_value = -1 , max_size_node = -1 ;
                    for ( edge * i = V [ o ] ; i != 0 ; i = i -> nxt ) 
                    if ( i -> p != father [ o ] && max_size_value < size [ i -> p ] ) {
                        max_size_value = size [ i -> p ] ; 
                        max_size_node = i -> p ;
                    }
                    dfs ( max_size_node , t , h ) ;
                    for ( edge * i = V [ o ] ; i != 0 ; i = i -> nxt ) 
                    if ( i -> p != father [ o ] && i -> p != max_size_node ) dfs ( i -> p , i -> p , h + 1 ) ;
                }
            }
        }
    
        void cut_link ( ) {
            LINK_CUT :: dfs ( 0 , 0 , 0 ) ; 
            for ( int i = 0 ; i < N ; ++ i ) Seg :: value [ num [ i ] ] = :: value [ i ] ; 
            Seg :: build () ;
        }
    
        void modify ( const int p , const int v ) {
            Seg :: modify ( num [ p ] , v ) ;
        }
    
        int Qsum ( int a , int b ) {
            int v = 0 ;
            while ( top [ a ] != top [ b ] ) {
                if ( height [ a ] < height [ b ] ) swap ( a , b ) ;
                v += Seg :: Qsum ( num [ a ] , num [ top [ a ] ] ) ;
                a = father [ top [ a ] ] ;
            }
            v += Seg :: Qsum ( num [ a ] , num [ b ] ) ;
            return v ; 
        }
    
        int Qmax ( int a , int b ) {
            int v = -( 1 << 30 ) ;
            while ( top [ a ] != top [ b ] ) {
                if ( height [ a ] < height [ b ] ) swap ( a , b ) ; 
                max_equal ( v , Seg :: Qmax ( num [ a ] , num [ top [ a ] ] ) ) ;
                a = father [ top [ a ] ] ;
            }
            max_equal ( v , Seg :: Qmax ( num [ a ] , num [ b ] ) ) ;
            return v ; 
        }
    
    }
    
    char c [ 10 ] ;
    int main () {
        scanf ( "%d" , & N ) ;
        for ( int i = 1 ; i < N ; ++ i ) {
            int a , b ; 
            scanf ( "%d%d" , & a , & b ) ;
            add_edge ( a - 1 , b - 1 ) ;
        }
        for ( int i = 0 ; i < N ; ++ i ) scanf ( "%d" , & value [ i ] ) ;
        Link_cut :: Get_size () ; 
        Link_cut :: cut_link () ;
        
        scanf ( "%d" , & Q ) ;
        for ( int i = 0 ; i < Q ; ++ i ) {
            int a , b ; 
            scanf ( "%s%d%d" , c , & a , & b ) ;
            switch ( c [ 1 ] ) {
                case 'H' : 
                    Link_cut :: modify ( a - 1 , b ) ;
                    break ;
                case 'M' :
                    printf ( "%d
    " , Link_cut :: Qmax ( a - 1 , b - 1 ) ) ; 
                    break ;
                case 'S' :
                    printf ( "%d
    " , Link_cut :: Qsum ( a - 1 , b - 1 ) ) ;
                    break ;
            }
        }
    
        return 0 ;
    }

    本博客禁止转载,转载请先联系作者,谢谢。 

    原地址:http://www.cnblogs.com/Christopher-Cao/p/5186126.html

    如发现与文章与地址不同,请通过博客联系作者

  • 相关阅读:
    前端从头再出发之表单
    百度前端学院第19天作业
    百度前端学院第17到18天和第16天的作业
    百度前端学院第九天到第11天笔记
    自己爬虫的几个案例
    Magnum Kubernetes源码分析(一)
    magnum devstack部署
    kubernetes service分析
    玩转docker镜像和镜像构建
    Dockerfile与Docker构建流程解读
  • 原文地址:https://www.cnblogs.com/Christopher-Cao/p/5186126.html
Copyright © 2011-2022 走看看