Cod sursa(job #1203746)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 1 iulie 2014 11:17:03
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.5 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

class SegmentTree
{
public:

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

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

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

private:

    vector <int> T;
    int N;

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

            build( 2 * node, st, m, values );
            build( 2 * node + 1, m + 1, dr, values );

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

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

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

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

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

            if ( st_q <= m )
                val = max( val, query( 2 * node, st, m, st_q, dr_q ) );

            if ( m  < dr_q )
                val = max( val, query( 2 * node + 1, m + 1, dr, st_q, dr_q ) );

            return val;
        }
    }
};

const int Nmax = 1e5 + 2;

vector <SegmentTree> ST;
vector <int> G[Nmax];
int size[Nmax], path[Nmax], pos_in_path[Nmax], path_length[Nmax], start_node[Nmax];
int depth[Nmax], father[Nmax], valueNode[Nmax];

int N, nrPaths, Q;

void DFS( int node )
{
    int heavySon = 0;
    size[node] = 1;

    for ( auto x: G[node] )
    {
        if ( father[x] == 0 )
        {
            depth[x] = depth[node] + 1;
            father[x] = node;

            DFS( x );

            size[node] += size[x];

            if ( size[x] > size[heavySon] )
                heavySon = x;
        }
    }

    if ( heavySon == 0 )
        path[node] = nrPaths++;
    else
        path[node] = path[heavySon];

    pos_in_path[node] = path_length[ path[node] ]++;
}

void build_heavy_path()
{
    father[1] = 1;
    depth[1] = 0;

    DFS( 1 );

    for ( int i = 1; i <= N; ++i )
    {
        pos_in_path[i] = path_length[ 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>> pathValues = vector < vector<int> >( nrPaths );

    for ( int i = 0; i < nrPaths; ++i )
        pathValues[i] = vector<int>( path_length[i] );

    for ( int i = 1; i <= N; ++i )
        pathValues[ path[i] ][ pos_in_path[i] ] = valueNode[i];

    for ( int i = 0; i < nrPaths; ++i )
        ST.push_back( SegmentTree( pathValues[i].size(), pathValues[i] ) );
}

void update( int node, int value )
{
    valueNode[node] = value;

    ST[ path[node] ].update( pos_in_path[node], value );
}

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

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

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

    in.sync_with_stdio( false );

    in >> N >> Q;

    for ( int i = 1; i <= N; ++i )
        in >> valueNode[i];

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

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

    build_heavy_path();
    build_segment_trees();

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

        if ( tip == 0 )
        {
            update( a, b );
        }
        else
        {
            out << query( a, b ) << "\n";
        }
    }

    return 0;
}