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\n" , Link_cut :: Qmax ( a - 1 , b - 1 ) ) ; 
                break ;
            case 'S' :
                printf ( "%d\n" , Link_cut :: Qsum ( a - 1 , b - 1 ) ) ;
                break ;
        }
    }

    return 0 ;
}

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

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

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

posted @ 2016-02-10 21:18  Chris_2  阅读(209)  评论(2编辑  收藏  举报