Cod sursa(job #2918229)

Utilizator vladburacBurac Vlad vladburac Data 10 august 2022 16:06:35
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.43 kb
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5;

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

int n;
int val[MAXN+1], depth[MAXN+1], parent[MAXN+1], sz[MAXN+1], heavyChild[MAXN+1], valueInOrder[MAXN+1], chain[MAXN+1];
int label[MAXN+1], nr = 0;
int maxi[MAXN+1], indexx[MAXN+1];
int aint[2*MAXN+1];
vector <int> edges[MAXN+1];

void build( int node, int left, int right ) {
  if( left == right ) {
    aint[node] = valueInOrder[left];
    return;
  }
  int mid, leftSon, rightSon;
  mid = ( left + right ) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * ( mid - left + 1 );
  build( leftSon, left, mid );
  build( rightSon, mid + 1, right );
  aint[node] = max( aint[leftSon], aint[rightSon] );
}

void update( int node, int left, int right, int poz, int val ) {
  if( left == right ) {
    aint[node] = val;
    return;
  }
  int mid, leftSon, rightSon;
  mid = ( left + right ) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * ( mid - left + 1 );
  if( poz <= mid )
    update( leftSon, left, mid, poz, val );
  else
    update( rightSon, mid + 1, right, poz, val );
  aint[node] = max( aint[leftSon], aint[rightSon] );
}

int query( int node, int left, int right, int qleft, int qright ) {
  if( left >= qleft && right <= qright )
    return aint[node];
  if( left > qright || right < qleft )
    return -1;
  int ans = -1;
  int mid, leftSon, rightSon;
  mid = ( left + right ) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * ( mid - left + 1 );
  if( qleft <= mid )
    ans = max( ans, query( leftSon, left, mid, qleft, qright ) );
  if( qright > mid )
    ans = max( ans, query( rightSon, mid + 1, right, qleft, qright ) );
  return ans;
}

void dfs( int node, int height ) {
  depth[node] = height;
  sz[node] = 1;
  maxi[node] = indexx[node] = -1;
  for( auto vec: edges[node] ) {
    if( vec != parent[node] ) {
      parent[vec] = node;
      dfs( vec, height + 1 );
      sz[node] += sz[vec];
      if( sz[vec] > maxi[node] ) {
        maxi[node] = sz[vec];
        indexx[node] = vec;
      }
    }
  }
  heavyChild[node] = indexx[node];
}

void dfs_labels( int node ) {
  label[node] = nr++;
  if( heavyChild[node] != -1 ) {
    chain[heavyChild[node]] = chain[node];
    dfs_labels( heavyChild[node] );
  }
  for( auto vec: edges[node] ) {
    if( vec != parent[node] && vec != heavyChild[node] ) {
      dfs_labels( vec );
    }
  }
}

int solve( int a, int b ) {
  if( chain[a] == chain[b] ) {
    if( label[a] > label[b] )
      swap( a, b );
    return query( 0, 0, n - 1, label[a], label[b] );
  }
  if( depth[chain[a]] < depth[chain[b]] )
    swap( a, b );
  return max( query( 0, 0, n - 1, label[chain[a]], label[a] ), solve( parent[chain[a]], b ) );
}
int main() {
  int q, i, x, y, op;
  fin >> n >> q;
  for( i = 0; i < n; i++ )
    fin >> val[i], chain[i] = i;
  for( i = 0; i < n - 1; i++ ) {
    fin >> x >> y;
    x--, y--;
    edges[x].push_back( y );
    edges[y].push_back( x );
  }
  dfs( 0, 0 );
  dfs_labels( 0 );
  for( i = 0; i < n; i++ )
    valueInOrder[label[i]] = val[i];
  //for( i = 0; i < n; i++ )
    //cout << valueInOrder[i] << " ";
  build( 0, 0, n - 1 );
  //cout << query( 0, 0, n - 1, 0, 2 );
  for( i = 0; i < q; i++ ) {
    fin >> op >> x >> y;
    if( op == 0 )
      update( 0, 0, n - 1, label[x-1], y );
    else
      fout << solve( x - 1, y - 1 ) << "\n";
  }
  return 0;
}