Cod sursa(job #3289889)

Utilizator pacelaaaCiurea Pavel pacelaaa Data 29 martie 2025 00:07:59
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin ( "heavypath.in");
ofstream fout ( "heavypath.out" );

#define cin fin
#define cout fout
#define PB push_back
#define F first
#define S second
#define FR( a, b) for( int a = 0; a < (int) b; a ++ )
#define FOR( a, c, b) for( int a = c; a < (int) b; a ++ )


const int Nmax = 1e5 + 1;
const int Log = 17;

struct node {
  int val;
  int path, poz_aint;
  int adancime = -1, parinte;
  int sz = 1;
};

int aint[4 * Nmax], ce_nod[Nmax], parinte[Log][Nmax];
node v[Nmax];

vector< vector<int> > path;
vector< int > adj[Nmax];

void print_node( node nod ) {
  cout << " Nod\n" << nod.val << " parinte " << nod.parinte << " adancime " << nod.adancime << " poz_aint " << nod.poz_aint << " path " << nod.path << " sz " << nod.sz << '\n';
}

bool cmp( int a, int b ) {
  return v[a].adancime > v[b].adancime;
}

void dfs( int nod, int parinte ) {
  int heavy_son, sz_heavy;

  v[nod].adancime = v[parinte].adancime + 1;
  v[nod].parinte = parinte;

  if( adj[nod].size() == 1 && nod != 1 ) {
    path.push_back( {nod} );
    v[nod].sz = 1;
    v[nod].path = path.size() - 1;
  } else {
    sz_heavy = 0;
    FR( i, adj[nod].size() ) {
      int son = adj[nod][i];
      if ( son != parinte ) {
        dfs( son, nod );

        v[nod].sz += v[son].sz;
        if( v[son].sz > sz_heavy ) {
          sz_heavy = v[son].sz;
          heavy_son = son;
        }
      }
    }

    v[nod].path = v[heavy_son].path;
    path[ v[nod].path ].PB( nod );
  }
}

void sort_paths() {
  int prev_len = 1;
  FR( i, path.size() ) {
    sort( path[i].begin(), path[i].end(), cmp );
    /*cout << i << " suntem in sort " << '\n';
    FR( j, path[i].size() )
      cout << path[i][j] << " ";
    cout << '\n';*/
    FR( j, path[i].size() ) {
      int nod = path[i][j];
      v[nod].poz_aint = prev_len + j;
      ce_nod[prev_len + j] = nod;
    }
    prev_len += path[i].size();
  }
}

void init( int l_range, int r_range, int poz ) {
  if( l_range == r_range ) {
    aint[poz] = v[ ce_nod[l_range] ].val;
    return;
  }

  int mij = ( l_range + r_range ) / 2;

  init( l_range, mij, 2 * poz );
  init( mij + 1, r_range, 2 * poz + 1 );
  aint[poz] = max( aint[2 * poz], aint[2 * poz + 1] );
}

void update( int l_range, int r_range, int target, int poz, int val ) {
  if ( l_range > target || r_range < target )
    return;

  if( l_range == r_range ) {
    aint[poz] = val;
    return;
  }

  int mij = ( l_range + r_range ) / 2;

  update( l_range, mij, target, 2 * poz, val );
  update( mij + 1, r_range, target, 2  * poz + 1, val );
  aint[poz] = max( aint[2 * poz], aint[2 * poz + 1] );
}

int query( int l_range, int r_range, int l_target, int r_target, int poz ) {
  if ( l_range > r_target || r_range < l_target )
    return 0;

  if( l_range >= l_target && r_range <= r_target )
    return aint[poz];

  int mij = ( l_range + r_range ) / 2;
  int a = query( l_range, mij, l_target, r_target, 2 * poz );
  int b = query( mij + 1, r_range, l_target, r_target, 2 * poz  + 1);
  return max( a, b );
}

int lca( int u, int nod ) {
  if( v[u].adancime < v[nod].adancime )
    swap( u, nod );

  int lev_dif = v[u].adancime - v[nod].adancime, de_urcat = 0;
  while( lev_dif > 0 ) {
    if( lev_dif % 2 == 1 )
      u = parinte[de_urcat][u];
    lev_dif /= 2;
    de_urcat++;
  }
  if( u == nod )
    return u;

  de_urcat = Log;
  for( de_urcat = Log - 1; de_urcat >= 0; de_urcat-- )
    if( parinte[de_urcat][u] != parinte[de_urcat][nod] )
      u = parinte[de_urcat][u], nod = parinte[de_urcat][nod];

  return parinte[0][u];
}

int query_nodParinte( int u, int parent ) {
  int ans = 0, pathU;

  while( v[u].path != v[parent].path ) {
    pathU = v[u].path;
    int r = path[pathU][path[pathU].size() - 1];

    ans = max( ans, query( 1, Nmax, v[u].poz_aint, v[r].poz_aint, 1 ) );
    u = v[r].parinte;
  }

  ans = max( ans, query( 1, Nmax, v[u].poz_aint, v[parent].poz_aint, 1 ) );
  return ans;
}

int real_query( int u, int nod ) {
  int lca1 = lca( u, nod );

  return max( query_nodParinte(u, lca1), query_nodParinte( nod, lca1 ) );
}

int main()
{
    int n, queries, tip, val, nod, u;

    cin >> n >> queries;

    FOR( i, 1, n + 1 )
      cin >> v[i].val;

    FR( i, n - 1 ) {
      cin >> u >> nod;
      adj[u].PB( nod );
      adj[nod].PB( u );
    }

    dfs( 1, 0 );
    sort_paths();


    FOR( i, 1, n + 1 )
      parinte[0][i] = v[i].parinte;
    FOR( i, 1, Log ) {
      FOR( nod, 1, n + 1 )
        parinte[i][nod] = parinte[i - 1][parinte[i-1][nod]];
    }

    /*FOR( i, 1, n + 1 )
      print_node( v[i] );*/

    init( 1, Nmax, 1 );
    //cout << "LCA " << lca( 9, 4 ) << '\n';

    while( queries-- ) {
      cin >> tip >> nod;
      if( tip == 0 ) {
        cin >> val;
        update( 1, Nmax, v[nod].poz_aint, 1, val );
      } else {
        cin >> u;
        cout << real_query( nod, u ) << '\n';
      }
    }
    return 0;
}