BZOJ-3242: [Noi2013]快餐店(线段树)

作者: AmadeusChan | 来源:发表于2019-03-13 12:57 被阅读0次

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3242

    考虑如果图是一棵树的情况,那么理所当然选址是直径的中间,如果是环套树,那么由于最短路组成一棵树,所以是删去环上一条边组成的所有树的直径的最小值的一半,那么我们把环找出来,从中间一出断开,就可以用线段树求出直径在环上的情况,不在环上的情况分开处理即可。

    代码:

    #include <cstdio>
    
    #include <algorithm>
    
    #include <cstring>
    
     
    
    using namespace std ;
    
     
    
    #define travel( x ) for ( edge *p = head[ x ] ; p ; p = p -> next )
    
    #define rep( i , x ) for ( int i = 0 ; i ++ < x ; )
    
    #define REP( i , l , r ) for ( int i = l ; i <= r ; ++ i )
    
    #define Rep( i , x ) for ( int i = 0 ; i < x ; ++ i )
    
     
    
    typedef long long ll ;
    
     
    
    const int maxn = 101000 , maxm = 201000 , inf = 0x7fffffff ;
    
    const ll INF = ll( inf ) * ll( inf ) ;
    
     
    
    struct edge {
    
        edge *next ;
    
        int t , d ;
    
    } E[ maxm ] ;
    
     
    
    edge *pt = E , *head[ maxn ] ;
    
     
    
    inline void Init_edge(  ) {
    
        memset( head , 0 , sizeof( head ) ) ;
    
    }
    
     
    
    inline void add( int s , int t , int d ) {
    
        pt -> t = t , pt -> next = head[ s ] , pt -> d = d ;
    
        head[ s ] = pt ++ ;
    
    }
    
     
    
    inline void addedge( int s , int t , int d ) {
    
        add( s , t , d ) , add( t , s , d ) ;
    
    }
    
     
    
    int n , sta[ maxn ] , tp = 0 , pos[ maxn ] ;
    
    int ve[ maxn ] , vn = 0 , dn[ maxn ] , nxt[ maxn ] , lst[ maxn ] ;
    
    bool ud[ maxn ] , fg[ maxn ] ;
    
     
    
    void getC( int now , int fa ) {
    
        sta[ pos[ now ] = ++ tp ] = now , ud[ now ] = true ;
    
        travel( now ) if ( p -> t != fa ) {
    
            if ( vn ) return ;
    
            dn[ now ] = p -> d ;
    
            if ( ! ud[ p -> t ] ) {
    
                getC( p -> t , now ) ;
    
            } else {
    
                REP( i , pos[ p -> t ] , tp ) {
    
                    nxt[ vn ] = dn[ ve[ vn ] = sta[ i ] ] ;
    
                    vn ++ ;
    
                }
    
                Rep( i , vn ) lst[ i ] = nxt[ ( i - 1 + vn ) % vn ] , fg[ ve[ i ] ] = true ;
    
            }
    
        }
    
        ud[ now ] = false , tp -- ;
    
    }
    
     
    
    inline void upd( ll &x , ll &y , ll a ) {
    
        if ( a > x ) {
    
            y = x ;
    
            x = a ;
    
        } else if ( a > y ) y = a ;
    
    }
    
     
    
    inline void upd0( int &v , ll &d , int _v , ll _d ) {
    
        if ( _d > d ) {
    
            d = _d , v = _v ;
    
        }
    
    }
    
     
    
    inline void upd1( ll &x , ll y ) {
    
        if ( y > x ) x = y ;
    
    }
    
     
    
    ll dep[ maxn ][ 2 ] , dpth[ maxn ] , mh , dist[ maxn ] , ans ;
    
    int mv ;
    
     
    
    void geth( int now , int fa ) {
    
        upd0( mv , mh , now , dpth[ now ] ) ;
    
        travel( now ) if ( p -> t != fa && ! fg[ p -> t ] ) {
    
            dpth[ p -> t ] = dpth[ now ] + ll( p -> d ) ;
    
            geth( p -> t , now ) ;
    
        }
    
    }
    
     
    
    ll ans0 = 0 ;
    
     
    
    inline void upd2( ll &mx , ll &mx0 , ll &mx1 , ll _mx , ll _mx0 , ll _mx1 ) {
    
        mx = max( max( mx , _mx ) , mx0 + _mx1 ) ;
    
        mx0 = max( mx0 , _mx0 ) , mx1 = max( mx1 , _mx1 ) ;
    
    }
    
     
    
    struct node {
    
     
    
        node *lc , *rc ;
    
        int l , r , mid ;
    
        ll mx , mx0 , mx1 , tag ;
    
     
    
        inline void pushdown(  ) {
    
            if ( tag ) {
    
                mx0 += tag , mx1 -= tag ;
    
                if ( l < r ) {
    
                    lc -> tag += tag , rc -> tag += tag ;
    
                }
    
                tag = 0 ;
    
            }
    
        }
    
     
    
        inline void update(  ) {
    
            pushdown(  ) ;
    
            if ( l < r ) {
    
                lc -> pushdown(  ) , rc -> pushdown(  ) ;
    
                upd2( mx = lc -> mx , mx0 = lc -> mx0 , mx1 = lc -> mx1 , rc -> mx , rc -> mx0 , rc -> mx1 ) ;
    
            }
    
        }
    
     
    
    } sgt[ maxn << 1 ] ;
    
     
    
    typedef node* np ;
    
     
    
    np ptt = sgt , root ;
    
     
    
    void build( int l , int r , np &t ) {
    
        t = ptt ++ ;
    
        t -> l = l , t -> r = r ;
    
        if ( l == r ) {
    
            t -> mx = 0 , t -> mx0 = dep[ l ][ 0 ] - dist[ l ] , t -> mx1 = dep[ l ][ 0 ] + dist[ l ] , t -> tag = 0 ;
    
            return ;
    
        }
    
        t -> mid = ( l + r ) >> 1 ;
    
        build( l , t -> mid , t -> lc ) , build( t -> mid + 1 , r , t -> rc ) ;
    
        t -> update(  ) ;
    
    }
    
     
    
    void dec( int l , int r , ll d , np t ) {
    
        t -> pushdown(  ) ;
    
        if ( t -> l == l && r == t -> r ) {
    
            t -> tag += d ; return ;
    
        }
    
        if ( r <= t -> mid ) dec( l , r , d , t -> lc ) ; else
    
            if ( l > t -> mid ) dec( l , r , d , t -> rc ) ; else
    
                dec( l , t -> mid , d , t -> lc ) , dec( t -> mid + 1 , r , d , t -> rc ) ;
    
        t -> update(  ) ;
    
    }
    
     
    
    void change( int pos , ll mx0 , ll mx1 , np t ) {
    
        t -> pushdown(  ) ;
    
        if ( t -> l == t -> r ) {
    
            t -> mx = 0 , t -> mx0 = mx0 , t -> mx1 = mx1 ; return ;
    
        }
    
        change( pos , mx0 , mx1 , pos <= t -> mid ? t -> lc : t -> rc ) ;
    
        t -> update(  ) ;
    
    }
    
     
    
    void query( int l , int r , ll &mx , ll &mx0 , ll &mx1 , np t ) {
    
        if ( l > r ) {
    
            mx = mx0 = mx1 = 0 ; return ;
    
        }
    
        t -> pushdown(  ) ;
    
        if ( l == t -> l && r == t -> r ) {
    
            mx = t -> mx , mx0 = t -> mx0 , mx1 = t -> mx1 ;
    
            return ;
    
        }
    
        if ( r <= t -> mid ) query( l , r , mx , mx0 , mx1 , t -> lc  ) ; else
    
            if ( l > t -> mid ) query( l , r , mx , mx0 , mx1 , t -> rc ) ; else {
    
                query( l , t -> mid , mx , mx0 , mx1 , t -> lc ) ;
    
                ll a , b , c ; query( t -> mid + 1 , r , a , b , c , t -> rc ) ;
    
                upd2( mx , mx0 , mx1 , a , b , c ) ;
    
            }
    
    }
    
     
    
    int main(  ) {
    
        Init_edge(  ) ;
    
        scanf( "%d" , &n ) ;
    
        rep( i , n ) {
    
            int s , t , d ; scanf( "%d%d%d" , &s , &t , &d ) ; addedge( s , t , d ) ;
    
        }
    
        memset( pos , 0 , sizeof( pos ) ) , memset( ud , false , sizeof( ud ) ) , memset( fg , false , sizeof( fg ) ) ;
    
        getC( 1 , 0 ) ;
    
        Rep( i , vn ) {
    
            dep[ i ][ 0 ] = dep[ i ][ 1 ] = 0 ;
    
            int now = ve[ i ] ;
    
            travel( now ) if ( ! fg[ p -> t ] ) {
    
                dpth[ p -> t ] = mh = ll( p -> d ) ;
    
                geth( p -> t , now ) ;
    
                upd( dep[ i ][ 0 ] , dep[ i ][ 1 ] , mh ) ;
    
                dpth[ mv ] = mh = 0 ;
    
                geth( mv , 0 ) ;
    
                upd1( ans , mh ) ;
    
            }
    
            upd1( ans , dep[ i ][ 0 ] + dep[ i ][ 1 ] ) ;
    
        }
    
        ll temp = INF , a , b , c , x , y , z , sum = 0 ;
    
        dist[ 0 ] = 0 ;
    
        REP( i , 1 , ( vn - 1 ) ) dist[ i ] = dist[ i - 1 ] + ll( nxt[ i - 1 ] ) ;
    
        Rep( i , vn ) sum += nxt[ i ] ;
    
        build( 0 , vn - 1 , root ) ;
    
        Rep( i , vn ) {
    
            query( i , vn - 1 , a , b , c , root ) ;
    
            if ( i ) {
    
                query( 0 , i - 1 , x , y , z , root ) ;
    
                upd2( a , b , c , x , y , z ) ;
    
            }
    
            if ( a < temp ) temp = a ;
    
            dec( 0 , vn - 1 , nxt[ i ] , root ) ;
    
            ll d = sum - nxt[ i ] ;
    
            change( i , dep[ i ][ 0 ] - d , dep[ i ][ 0 ] + d , root ) ;
    
        }
    
        ans = max( ans , temp ) ;
    
        printf( "%.1f\n" , double( ans ) / 2.0 ) ;
    
        return 0 ;
    
    }
    

    相关文章

      网友评论

        本文标题:BZOJ-3242: [Noi2013]快餐店(线段树)

        本文链接:https://www.haomeiwen.com/subject/phmzpqtx.html