Cod sursa(job #3284079)

Utilizator elisa.ipateElisa Ipate elisa.ipate Data 10 martie 2025 23:03:43
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.72 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 aint[4 * nmax], perm_heavy[nmax], n;
vector <int> val;
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 query_heavy( int a, int b ) {
    int rez = 0;
    while( nod[a].next != nod[b].next ) {
        //cout << a << "a     " << b << "b\n";
        //cout << nod[a].time << " " << nod[nod[a].next].time << "\n";
        if( nod[a].level > nod[b].level ) {
            rez = max(rez, query(1, 1, n, nod[nod[a].next].time, nod[a].time));
            a = nod[nod[a].next].parent;
        } else {
            rez = max(rez, query(1, 1, n, nod[nod[b].next].time, nod[b].time));
            b = nod[nod[b].next].parent;
        }
    }
    //cout << "a " << a << " " << b << "\n";
    if( nod[b].time < nod[a].time )
        rez = max( rez, query( 1, 1, n, nod[b].time, nod[a].time ) );
    else
        rez = max( rez, query( 1, 1, n, nod[a].time, nod[b].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;
    val.resize( n );
    for( int i = 0; i < n; i++ )
        cin >> val[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 );
    for( int i = 1; i <= n; i++ )
        perm_heavy[nod[i].time] = val[i - 1];
    val.clear();
    init( 1, 1, n );
    for( int i = 0; i < m; i++ ) {
        cin >> t >> a >> b;
        if( t == 0 ) {
            perm_heavy[nod[a].time] = b;
            update(1, 1, n, nod[a].time );
        } else {
            max1 = query_heavy( a, b );
            cout << max1 << "\n";
        }
    }
    return 0;
}