Cod sursa(job #2980636)

Utilizator andrei_marciucMarciuc Andrei andrei_marciuc Data 16 februarie 2023 18:19:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.88 kb
#include <fstream>
#include <vector>
using namespace std;

ifstream cin( "heavypath.in" );
ofstream cout( "heavypath.out" );

const int MAXN = 1e5 + 1;
struct SegmentTree {
    int root, left, right;
    int SegmentTree[ 2 * MAXN ];

    void init( int minVal, int maxVal ) {
        root = 1;
        left = minVal;
        right = maxVal;
    }

    void update( int nod, int l, int r, int p, int x ) {
        if ( l == r ) {
            SegmentTree[ nod ] = x;
            return;
        }

        int med = ( l + r ) >> 1;
        int R = nod + 2 * ( med - l + 1 );
        int L = nod + 1;

        if( p <= med )
            update( L, l, med, p, x );
        else update( R, med + 1, r, p, x );
        SegmentTree[ nod ] = max( SegmentTree[ L ], SegmentTree[ R ] );
    }

    void update( int p, int x ) {
        update( root, left, right, p, x );
    }

    int query( int nod, int l, int r, int lq, int rq ) {
        if( r < lq || l > rq )
            return 0;
        if( lq <= l && r <= rq )
            return SegmentTree[ nod ];

        int med = ( l + r ) >> 1;
        int R = nod + 2 * ( med - l + 1 );
        int L = nod + 1;

        return max( query( L, l, med, lq, rq ), query( R, med + 1, r, lq, rq ) );
    }

    int query( int l, int r ) {
        return query( root, left, right, min( l, r ), max( l, r ) );
    }
};

struct Heavy {
    int poz;
    SegmentTree maxim;
    vector<int> pos, head;
    vector<int> heavy, depth;
    vector<int> parent, edges[ MAXN ];

    int dfs( int u, int p ) {
        int sizeV;
        int sizeU = 1;
        int maxSize = 0;
        heavy[ u ] = -1;
        parent[ u ] = p;
        for( int v : edges[ u ] )
            if( v != p ) {
                depth[ v ] = depth[ u ] + 1;
                sizeV = dfs( v, u );
                sizeU += sizeV;
                if( sizeV > maxSize ) {
                    maxSize = sizeV;
                    heavy[ u ] = v;
                }
            }

        return sizeU;
    }

    void decompose( int u, int p, int h ) {
        head[ u ] = h;
        pos[ u ] = poz++;
        if( heavy[ u ] != -1 )
            decompose( heavy[ u ], u, h );
        for( int v : edges[ u ] )
            if( v != p && v != heavy[ u ] )
                decompose( v, u, v );
    }

    void add_edge( int u, int v ) {
        edges[ u ].push_back( v );
        edges[ v ].push_back( u );
    }

    void init( int n ) {
        pos.resize( n + 1 );
        head.resize( n );
        heavy.resize( n );
        depth.resize( n );
        parent.resize( n );
        maxim.init( 0, n - 1 );
        poz = 0;
        dfs( 0, -1 );
        decompose( 0, -1, 0 );
    }

    void update( int u, int val ) {
        maxim.update( pos[ u ], val );
    }

    int query( int u, int v ) {
        int rez;

        rez = 0;
        while( head[ u ] != head[ v ] ) {
            if( depth[ head[ u ] ] > depth[ head[ v ] ] )
                swap( u, v );
            rez = max( rez, maxim.query( pos[ head[ v ] ], pos[ v ] ) );
            v = parent[ head[ v ] ];
        }
        if( depth[ head[ u ] ] > depth[ head[ v ] ] )
            swap( u, v );
        rez = max( rez, maxim.query( pos[ v ], pos[ u ] ) );

        return rez;
    }
};

int val[ MAXN ];
Heavy maxim;
int n, q;

int main()
{
    cin >> n >> q;
    for( int i = 0; i < n; i++ )
        cin >> val[ i ];

    int u, v;
    for( int i = 0; i < n - 1; i++ ) {
        cin >> u >> v;
        maxim.add_edge( u - 1, v - 1 );
    }

    maxim.init( n );
    for( int u = 0; u < n; u++ )
        maxim.update( u, val[ u ] );

    int type;
    while( q-- ) {
        cin >> type;
        cin >> u >> v;
        if( type == 0 )
            maxim.update( u - 1, v );
        else cout << maxim.query( u - 1, v - 1 ) << '\n';
    }
    return 0;
}