Cod sursa(job #1185088)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 14 mai 2014 23:08:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.3 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

class SegmentTree
{
public:

    SegmentTree( const int n, vector <int> &v )
    {
        N = n;
        T = vector <int>( 4 * N );
        build( 1, 0, N - 1, v );
    }

    void update( int pos, int val )
    {
        update( 1, 0, N - 1, pos, val );
    }

    int query( int st, int dr )
    {
        return query( 1, 0, N - 1, st, dr );
    }

private:

    vector <int> T;
    int N;

    void build( int nod, int st, int dr, vector <int> &v )
    {
        if ( st == dr )
        {
            T[nod] = v[st];
        }
        else
        {
            int m = ( st + dr ) / 2;

            build( 2 * nod, st, m, v );
            build( 2 * nod + 1, m + 1, dr, v );

            T[nod] = max( T[2 * nod], T[2 * nod + 1] );
        }
    }

    void update( int nod, int st, int dr, int pos, int val )
    {
        if ( st == dr )
        {
            T[nod] = val;
        }
        else
        {
            int m = ( st + dr ) / 2;

            if ( pos <= m ) update( 2 * nod, st, m, pos, val );
            else            update( 2 * nod + 1, m + 1, dr, pos, val );

            T[nod] = max( T[2 * nod], T[2 * nod + 1] );
        }
    }

    int query( int nod, int st, int dr, int st_q, int dr_q )
    {
        if ( st_q <= st && dr <= dr_q )
        {
            return T[nod];
        }
        else
        {
            int m = ( st + dr ) / 2;
            int sol = 0;

            if ( st_q <= m ) sol = max( sol, query( 2 * nod, st, m, st_q, dr_q ) );
            if (  m < dr_q ) sol = max( sol, query( 2 * nod + 1, m + 1, dr, st_q, dr_q ) );

            return sol;
        }
    }
};

const int Nmax = 100000 + 2;

vector <int> Graph[Nmax];
int value[Nmax];
int size[Nmax], father[Nmax], level[Nmax], path[Nmax], length_path[Nmax];
int pos_in_path[Nmax], start_node[Nmax];

vector <SegmentTree> SegmentTrees;
int Number_Of_Paths;

int N, Q;

void DFS( int nod )
{
    int heaviestSon = 0;
    size[nod] = 1;

    for ( auto son: Graph[nod] )
            if ( father[son] == 0 )
            {
                father[son] = nod;
                level[son] = level[nod] + 1;
                DFS( son );

                size[nod] += size[son];

                if ( size[heaviestSon] < size[son] )
                        heaviestSon = son;
            }

    if ( heaviestSon == 0 )
            path[nod] = Number_Of_Paths++;
    else
            path[nod] = path[heaviestSon];

    pos_in_path[nod] = length_path[ path[nod] ]++;
}

void build_heavy_path_decomposition()
{
    father[1] = 1;
    level[1] = 0;
    DFS( 1 );

    for ( int i = 1; i <= N; ++i )
    {
        pos_in_path[i] = length_path[ path[i] ] - pos_in_path[i] - 1;

        if ( pos_in_path[i] == 0 )
                start_node[ path[i] ] = i;
    }
}

void build_segment_trees()
{
    vector < vector<int> > pathValue = vector < vector<int> >( Number_Of_Paths );

    for ( int i = 0; i < Number_Of_Paths; ++i )
            pathValue[i] = vector<int>( length_path[i] );

    for ( int i = 1; i <= N; ++i )
            pathValue[ path[i] ][ pos_in_path[i] ] = value[i];

    for ( int i = 0; i < Number_Of_Paths; ++i )
            SegmentTrees.push_back( SegmentTree( pathValue[i].size(), pathValue[i] ) );
}

int query( int x, int y )
{
    if ( level[ start_node[ path[x] ] ] < level[ start_node[ path[y] ] ] )
            swap( x, y );

    if ( path[x] == path[y] )
            return SegmentTrees[ path[x] ].query( min( pos_in_path[x], pos_in_path[y] ), max( pos_in_path[x], pos_in_path[y] ) );
    else
            return max( SegmentTrees[ path[x] ].query( 0, pos_in_path[x] ), query( father[ start_node[ path[x] ] ], y ) );
}

int main()
{
    ifstream f("heavypath.in");
    ofstream g("heavypath.out");

    f >> N >> Q;

    for ( int i = 1; i <= N; ++i )
            f >> value[i];

    for ( int i = 1, a, b; i < N; ++i )
    {
        f >> a >> b;

        Graph[a].push_back( b );
        Graph[b].push_back( a );
    }

    build_heavy_path_decomposition();
    build_segment_trees();

    for ( int i = 1, tip, a, b; i <= Q; ++i )
    {
        f >> tip >> a >> b;

        if ( tip == 0 )
        {
            value[a] = b;
            SegmentTrees[ path[a] ].update( pos_in_path[a], b );
        }
        else
        {
            g << query( a, b ) << "\n";
        }
    }

    return 0;
}