Cod sursa(job #2990505)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 7 martie 2023 23:11:24
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.13 kb
// This program was written
// by Mircea Rebengiuc
// for problem heavypath
// on 07.03.2023

#include <stdio.h>
#include <ctype.h>

#include <vector>

#define magic_sauce inline __attribute__((always_inline))

magic_sauce int max( int a, int b ){ return a > b ? a : b; }
magic_sauce int min( int a, int b ){ return a < b ? a : b; }

FILE *fin, *fout;

magic_sauce int fgetint(){
  int n = 0, ch;

  while( !isdigit( ch = fgetc( fin ) ) );
  do
    n = n * 10 + ch - '0';
  while( isdigit( ch = fgetc( fin ) ) );

  return n;
}

const int MAXN = 1e5;
const int AINTS = (1 << 18);
const int INF = 1e9;

int v[MAXN];
std::vector<int> adj[MAXN];
int head[MAXN];
int par[MAXN];
int siz[MAXN];
int idx[MAXN];
int dep[MAXN];
int tidx;

int aint[AINTS];
int aintn;

void size_pre( int u, int p, int d ){
  par[u] = p;
  siz[u] = 1;
  dep[u] = d;

  for( int v : adj[u] )
    if( v != p ){
      size_pre( v, u, d + 1 );
      siz[u] += siz[v];
    }
}

void heavy( int u, int p, int h ){
  int maxs = -1, maxv = -1;

  head[u] = h;
  aint[aintn - 1 + tidx] = v[u];
  idx[u] = tidx++;

  for( int v : adj[u] )
    if( v != p ){
      if( siz[v] > maxs ){
        maxs = siz[v];
        maxv = v;
      }
    }

  if( maxv > 0 )
    heavy( maxv, u, h );

  for( int v : adj[u] )
    if( v != p && v != maxv )
      heavy( v, u, v );
}

magic_sauce int aintq( int ql, int qr ){
  int ret = -INF;

  if( ql > qr ){
    int aux = ql;
    ql = qr;
    qr = aux;
  }

  ql += aintn - 1;
  qr += aintn - 1;
  while( ql < qr ){
    if( (ql & 1) == 0 ){
      ret = max( ret, aint[ql] );
      ql++;
    }

    ql = (ql - 1) >> 1;

    if( (qr & 1) ){
      ret = max( ret, aint[qr] );
      qr--;
    }

    qr = (qr - 1) >> 1;
  }

  if( ql == qr )
    ret = max( ret, aint[ql] );

  return ret;
}

magic_sauce void aintu( int idx, int newv ){
  idx += aintn - 1;
  aint[idx] = newv;

  do{
    idx = (idx - 1) >> 1;
    aint[idx] = max( aint[(idx << 1) + 1], aint[(idx << 1) + 2] );
  }while( idx );
}

magic_sauce int query( int a, int b ){
  int ret = -INF;

  while( head[a] != head[b] ){
    if( dep[a] > dep[b] ){ // ridicam a?
      ret = max( ret, aintq( idx[a], idx[head[a]] ) );
      a = par[head[a]];
    }else{ // ridicam b?
      ret = max( ret, aintq( idx[b], idx[head[b]] ) );
      b = par[head[b]];
    }
  }

  return max( ret, aintq( idx[a], idx[b] ) );
}

magic_sauce void update( int u, int newv ){
  aintu( idx[u], newv );
}

int main(){
  fin  = fopen( "heavypath.in",  "r" );
  fout = fopen( "heavypath.out", "w" );

  int n, i, q, a, b, op;

  n = fgetint();
  aintn = 1;
  while( aintn < n )
    aintn <<= 1;
  
  q = fgetint();
  for( i = 0 ; i < n ; i++ )
    v[i] = fgetint();

  for( i = 1 ; i < n ; i++ ){
    a = fgetint() - 1;
    b = fgetint() - 1;

    adj[a].push_back( b );
    adj[b].push_back( a );
  }

  size_pre( 0, 0, 0 );
  tidx = 0;
  heavy( 0, 0, 0 );

  for( i = aintn - 1 ; i-- ; )
    aint[i] = max( aint[(i << 1) + 1], aint[(i << 1) + 2] );

  for( ; q-- ; ){
    op = fgetint();

    a = fgetint() - 1;

    if( op )
      fprintf( fout, "%d\n", query( a, fgetint() - 1 ) );
    else
      update( a, fgetint() );
  }

  fclose( fin );
  fclose( fout );
  return 0;
}