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
如发现与文章与地址不同,请通过博客联系作者