Cod sursa(job #2892470)

Utilizator LucaMihaiLM10Luca Ilie LucaMihaiLM10 Data 22 aprilie 2022 11:58:02
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.75 kb
#include <bits/stdc++.h>

#define MAX_N 100000

using namespace std;

struct SGT {
    int root, left, right;
    int sgt[4 * MAX_N];

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

    void update( int nod, int l, int r, int p, int x ) {
        int mid;

        if ( l == r ) {
            sgt[nod] = x;
            return;
        }

        mid = (l + r) / 2;
        if ( p <= mid )
            update( nod * 2 + 1, l, mid, p, x );
        else
            update( nod * 2 + 2, mid + 1, r, p, x );
        sgt[nod] = max( sgt[nod * 2 + 1], sgt[nod * 2 + 2] );
    }

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

    int query( int nod, int l, int r, int lq, int rq ) {
        int mid;

        if ( r < lq || l > rq )
            return 0;
        if ( lq <= l && r <= rq )
            return sgt[nod];

        mid = (l + r) / 2;
        return max( query( nod * 2 + 1, l, mid, lq, rq ), query( nod * 2 + 2, mid + 1, r, lq, rq ) );
    }

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

struct HPD {
    int crt_pos;
    vector <int> pos, head, heavy, depth, parent, edges[MAX_N];
    SGT maxim;

    int dfs( int u, int p ) {
        int maxSize, sizeU, sizeV;

        parent[u] = p;
        sizeU = 1;
        maxSize = 0;
        heavy[u] = -1;
        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] = crt_pos++;
        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 );
        head.resize( n );
        heavy.resize( n );
        depth.resize( n );
        parent.resize( n );
        maxim.init( 0, n - 1 );
        crt_pos = 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 ans;

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

        return ans;
    }
};

int val[MAX_N];
HPD maxim;

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

    int n, m, tip, u, v, x, i;

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

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

    while ( m-- ) {
        cin >> tip;

        if ( tip == 0 ) {
            cin >> u >> x;
            maxim.update( u - 1, x );
        } else {
            cin >> u >> v;
            cout << maxim.query( u - 1, v - 1 ) << "\n";
        }
    }

    return 0;
}