Cod sursa(job #3284064)

Utilizator elisa.ipateElisa Ipate elisa.ipate Data 10 martie 2025 22:10:14
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.39 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;
const int nmax = 1e5 + 1;
const int MAXLOG = 18;
struct info{
    int size, next, parent, time, level;
};
info nod[nmax];
int vertex[nmax], aint[4 * nmax], perm_heavy[nmax], lca[MAXLOG][nmax], n;

vector <int> edges[nmax];
void init( int nod, int l, int r ) {
    if( l == r ) {
        aint[nod] = perm_heavy[l];
        return;
    }
    init( 2 * nod, l, (l + r) / 2 );
    init( 2 * nod + 1, (l + r) / 2 + 1, r );
    aint[nod] = max( aint[2 * nod], aint[2 * nod + 1] );
}

int query( int nod, int l, int r, int lq, int rq ) {
    if( r < lq || rq < l )
        return 0;
    if( lq <= l && r <= rq )
        return aint[nod];
    return max(query(2 * nod, l, (l + r) / 2, lq, rq), query(2 * nod + 1, (l + r) / 2 + 1, r, lq, rq) );
}

void update( int nod, int l, int r, int poz_update ) {
    if( poz_update < l || poz_update > r )
        return;
    if( l == r ) {
        aint[nod] = perm_heavy[l];
        return;
    }
    update( 2 * nod, l, (l + r) / 2, poz_update );
    update( 2 * nod + 1, (l + r) / 2 + 1, r, poz_update );
    aint[nod] = max( aint[2 * nod], aint[2 * nod + 1] );
}

void find_size( int vf, int parinte, int lev ) {
    nod[vf].level = lev;
    nod[vf].parent = parinte;
    nod[vf].size = 1;
    if( vf != 1 && edges[vf].size() == 1 )
        return;
    for( int fiu: edges[vf] ) {
        if( fiu == parinte )
            continue;
        find_size( fiu, vf, lev + 1 );
        nod[vf].size += nod[fiu].size;
    }
}

int timp = 1;
void find_heavy( int vf, int next ) {
    int maxx = 0, max_fiu;
    nod[vf].time = timp;
    timp++;
    nod[vf].next = next;
    if( nod[vf].size == 1 )
        return;
    for( int i = 0; i < edges[vf].size(); i++ ) {
        if( edges[vf][i] != nod[vf].parent ) {
            if( nod[edges[vf][i]].size > maxx ) {
                maxx = nod[edges[vf][i]].size;
                max_fiu = edges[vf][i];
            }
        }
    }
    find_heavy( max_fiu, next );
    for( int i = 0; i < edges[vf].size(); i++ ) {
        if( edges[vf][i] != nod[vf].parent && edges[vf][i] != max_fiu )
            find_heavy( edges[vf][i], edges[vf][i] );
    }
}

int urca_niv( int vf, int niv ) {
    int ind_p2 = 0;
    while( niv > 0 ) {
        if( niv % 2 == 1 )
            vf = lca[ind_p2][vf];
        ind_p2++;
        niv /= 2;
    }
    return vf;
}

int find_lca( int a, int b ) {
    int lev_a = nod[a].level, lev_b = nod[b].level;
    if( lev_a > lev_b )
        a = urca_niv( a, lev_a - lev_b );
    else
        b = urca_niv( b, lev_b - lev_a );
    int i = MAXLOG - 1;
    while( i >= 0 && a != b ) {
        if( lca[i][a] != lca[i][b] ) {
            a = lca[i][a];
            b = lca[i][b];
        }
        i--;
    }
    if( a != b )
        return lca[0][a];
    return a;
}

int query_heavy( int a, int b ) {
    // level[a] > level[b]
    int rez = 0;
    while( nod[a].next != nod[b].next ) {
        //cout << a << "     " << nod[a].next << "    ";
        //cout << nod[a].time << " " << nod[nod[a].next].time << "\n";
        rez = max( rez, query( 1, 1, n, nod[nod[a].next].time, nod[a].time ) );
        a = nod[nod[a].next].parent;
    }
    //cout << "a " << a << " " << b << "\n";
    rez = max( rez, query( 1, 1, n, nod[b].time, nod[a].time ) );
    return rez;
}

int main() {
    ifstream cin("heavypath.in" );
    ofstream cout("heavypath.out" );
    int m, t, a, b;
    int max1, max2;
    int x, y;
    cin >> n >> m;
    for( int i = 1; i <= n; i++ )
        cin >> vertex[i];
    for( int i = 1; i < n; i++ ) {
        cin >> x >> y;
        edges[x].push_back(y);
        edges[y].push_back(x);
    }
    find_size( 1, 0, 1 );
    find_heavy( 1, 1 );
    cout << "\n";
    for( int i = 1; i <= n; i++ ) {
        perm_heavy[nod[i].time] = vertex[i];
        //cout << nod[i].time << " " << vertex[i] << "\n";
        lca[0][i] = nod[i].parent;
    }
    for( int i = 1; i < MAXLOG; i++ )
        for( int j = 1; j <= n; j++ )
            lca[i][j] = lca[i - 1][lca[i - 1][j]];
    init( 1, 1, n );
    for( int i = 0; i < m; i++ ) {
        cin >> t >> a >> b;
        if( t == 0 ) {
            vertex[a] = b;
            perm_heavy[nod[a].time] = b;
            update(1, 1, n, nod[a].time );
        } else {
            max1 = query_heavy( a, find_lca(a, b) );
            max2 = query_heavy( b, find_lca(a, b) );
            cout << max( max1, max2 ) << "\n";
        }
    }
    return 0;
}