Submission #44350

#TimeUsernameProblemLanguageResultExecution timeMemory
44350chonkaConstruction of Highway (JOI18_construction)C++98
0 / 100
8 ms3468 KiB
#include<iostream>
#include<stdio.h>
#include<vector>
#include<map>
#include<algorithm>
using namespace std ;

#define MAXN 100007
#define LOG 21

int n ;
pair < int , int > edge[ MAXN ] ;
vector < int > v[ MAXN ] ;
int c[ MAXN ] ;
int lvl[ MAXN ] ;

int heavy[ MAXN ] ;
int subtree[ MAXN ] ;
int LCA[ MAXN ][ LOG ] ;

int root[ MAXN ] ;
int pos_in_tree[ MAXN ] ;

map < int , int > ZX ;

int MXCOLOUR ;


class Tree {
    public :
    int tr[ 4 * MAXN ] ;
    int lazy[ 4 * MAXN ] ;
    void init ( int where , int IL , int IR ) {
        tr[ where ] = lazy[ where ] = 0 ;
        if ( IL == IR ) { return ; }
        int mid = ( IL + IR ) / 2 ;
        init ( 2 * where , IL , mid ) ;
        init ( 2 * where + 1 , mid + 1 , IR ) ;
    }
    void push_lazy ( int where , int IL , int IR ) {
        if ( lazy[ where ] == 0 ) { return ; }
        tr[ where ] = lazy[ where ] ;
        if ( IL != IR ) {
            lazy[ 2 * where ] = lazy[ where ] ;
            lazy[ 2 * where + 1 ] = lazy[ where ] ;
        }
        lazy[ where ] = 0 ;
        return ;
    }
    void update ( int where , int IL , int IR , int CURL , int CURR , int nwval ) {
        push_lazy ( where , IL , IR ) ;
        if ( IR < CURL || CURR < IL ) { return ; }
        if ( CURL <= IL && IR <= CURR ) {
            lazy[ where ] = nwval ;
            push_lazy ( where , IL , IR ) ;
            return ;
        }
        int mid = ( IL + IR ) / 2 ;
        update ( 2 * where , IL , mid , CURL , CURR , nwval ) ;
        update ( 2 * where + 1 , mid + 1 , IR , CURL , CURR , nwval ) ;
    }
    int query ( int where , int IL , int IR , int pos ) {
        push_lazy ( where , IL , IR ) ;
        if ( IR < pos || pos < IL ) { return -1 ; }
        if ( IL == IR ) { return tr[ where ] ; }
        int mid = ( IL + IR ) / 2 ;
        return max ( query ( 2 * where , IL , mid , pos ) , query ( 2 * where + 1 , mid + 1 , IR , pos ) ) ;
    }
};
Tree w ;


class inv_counter {
    public :
    long long tr[ 4 * MAXN ] ;
    void init ( int where , int IL , int IR ) {
        tr[ where ] = 0 ;
        if ( IL == IR ) { return ; }
        int mid = ( IL + IR ) / 2 ;
        init ( 2 * where , IL , mid ) ;
        init ( 2 * where + 1 , mid + 1 , IR ) ;
    }
    void update ( int where , int IL , int IR , int pos , int val ) {
        if ( IR < pos || pos < IL ) { return ; }
        if ( IL == IR ) { tr[ where ] += val ; return ; }
        int mid = ( IL + IR ) / 2 ;
        if ( pos <= mid ) {
            update ( 2 * where , IL , mid , pos , val ) ;
        }
        else {
            update ( 2 * where + 1 , mid + 1 , IR , pos , val ) ;
        }
        tr[ where ] = ( tr[ 2 * where ] + tr[ 2 * where + 1 ] ) ;
    }
    long long query ( int where , int IL , int IR , int CURL , int CURR ) {
        if ( CURL > CURR ) { return 0 ; }
        if ( IR < CURL || CURR < IL ) { return 0 ; }
        if ( CURL <= IL && IR <= CURR ) {
            return tr[ where ] ;
        }
        int mid = ( IL + IR ) / 2 ;
        return ( query ( 2 * where , IL , mid , CURL , CURR ) + query ( 2 * where + 1 , mid + 1 , IR , CURL , CURR ) ) ;
    }
};

inv_counter z ;

void init ( int vertex , int prv ) {
    int i ;
    int sz = v[ vertex ].size ( ) ;
    if ( prv != -1 ) {
        for ( i = 1 ; i < LOG ; i ++ ) {
            LCA[ vertex ][ i ] = LCA[ LCA[ vertex ][ i - 1 ] ][ i - 1 ] ;
        }
    }
    subtree[ vertex ] = 1 ;
    int mx , id ;
    mx = id = -1 ;
    for ( i = 0 ; i < sz ; i ++ ) {
        if ( v[ vertex ][ i ] == prv ) { continue ; }
        lvl[ v[ vertex ][ i ] ] = lvl[ vertex ] + 1 ;
        LCA[ v[ vertex ][ i ] ][ 0 ] = vertex ;
        init ( v[ vertex ][ i ] , vertex ) ;
        subtree[ vertex ] += subtree[ v[ vertex ][ i ] ] ;
        if ( mx < subtree[ v[ vertex ][ i ] ] ) {
            mx = subtree[ v[ vertex ][ i ] ] ;
            id = v[ vertex ][ i ] ;
        }
    }
    heavy[ vertex ] = id ;
}

void compress ( ) {
    vector < int > srt ;
    srt.clear ( ) ;
    int i ;
    for ( i = 1 ; i <= n ; i ++ ) {
        srt.push_back ( c[ i ] ) ;
    }
    sort ( srt.begin ( ) , srt.end ( ) ) ;
    int id = 1 ;
    ZX[ srt[ 0 ] ] = 1 ;
    for ( i = 1 ; i < n ; i ++ ) {
        if ( srt[ i ] == srt[ i - 1 ] ) { continue ; }
        id ++ ;
        ZX[ srt[ i ] ] = id ;
    }
    MXCOLOUR = id ;
    for ( i = 1 ; i <= n ; i ++ ) {
        c[ i ] = ZX[ c[ i ] ] ;
    }
}

int get_fst ( int x ) {
    int i ;
    int sr = w.query ( 1 , 1 , n , pos_in_tree[ x ] ) ;
    for ( i = LOG - 1 ; i >= 0 ; i -- ) {
        if ( LCA[ x ][ i ] != 0 ) {
            int ret = w.query ( 1 , 1 , n , pos_in_tree[ LCA[ x ][ i ] ] ) ;
            if ( ret == sr ) { x = LCA[ x ][ i ] ; }
        }
    }
    return x ;
}

void calc ( int st ) {
    int x = st ;
    vector < pair < long long , int > > aux ;
    aux.clear ( ) ;
    while ( x != 0 ) {
        int id = get_fst ( x ) ;
        aux.push_back ( make_pair ( lvl[ x ] - lvl[ id ] + 1 , w.query ( 1 , 1 , n , pos_in_tree[ id ] ) ) ) ;
        x = LCA[ id ][ 0 ] ;
    }
    int sz = aux.size ( ) ;
    long long ans = 0 ;
    int i , j ;
    for ( i = sz - 1 ; i >= 0 ; i -- ) {
        ans += aux[ i ].first * z.query ( 1 , 1 , MXCOLOUR , aux[ i ].second + 1 , MXCOLOUR ) ;
        z.update ( 1 , 1 , MXCOLOUR , aux[ i ].second , aux[ i ].first ) ;
    }
    printf ( "%lld\n" , ans ) ;
    for ( i = 0 ; i < sz ; i ++ ) {
        z.update ( 1 , 1 , MXCOLOUR , aux[ i ].second , -aux[ i ].first ) ;
    }
}

void input ( ) {
    scanf ( "%d" , &n ) ;
    int i ;
    for ( i = 1 ; i <= n ; i ++ ) {
        scanf ( "%d" , &c[ i ] ) ;
    }
    for ( i = 1 ; i < n ; i ++ ) {
        scanf ( "%d%d" , &edge[ i ].first , &edge[ i ].second ) ;
        v[ edge[ i ].first ].push_back ( edge[ i ].second ) ;
        v[ edge[ i ].second ].push_back ( edge[ i ].first ) ;
    }
    compress ( ) ;
}

void solve ( ) {
    init ( 1 , -1 ) ;
    int i ;
    int pos = 0 ;
    for ( i = 1 ; i <= n ; i ++ ) {
        if ( i == 1 || heavy[ LCA[ i ][ 0 ] ] != i ) {
            int x = i ;
            while ( x != -1 ) {
                pos ++ ;
                pos_in_tree[ x ] = pos ;
                root[ x ] = i ;
                x = heavy[ x ] ;
            }
        }
    }
    w.init ( 1 , 1 , n ) ;
    w.update ( 1 , 1 , n , pos_in_tree[ 1 ] , pos_in_tree[ 1 ] , c[ 1 ] ) ;
    z.init ( 1 , 1 , MXCOLOUR ) ;
    for ( i = 1 ; i < n ; i ++ ) {
        calc ( edge[ i ].first ) ;
        int x = edge[ i ].second ;
        while ( x != 0 ) {
            w.update ( 1 , 1 , n , pos_in_tree[ root[ x ] ] , pos_in_tree[ x ] , c[ edge[ i ].second ] ) ;
            x = LCA[ root[ x ] ][ 0 ] ;
        }
    }
}

int main ( ) {
    input ( ) ;
    solve ( ) ;
    return 0 ;
}

Compilation message (stderr)

construction.cpp: In function 'void calc(int)':
construction.cpp:177:13: warning: unused variable 'j' [-Wunused-variable]
     int i , j ;
             ^
construction.cpp: In function 'void input()':
construction.cpp:189:11: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf ( "%d" , &n ) ;
     ~~~~~~^~~~~~~~~~~~~
construction.cpp:192:15: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf ( "%d" , &c[ i ] ) ;
         ~~~~~~^~~~~~~~~~~~~~~~~~
construction.cpp:195:15: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf ( "%d%d" , &edge[ i ].first , &edge[ i ].second ) ;
         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...