Mai intai trebuie sa te autentifici.

Cod sursa(job #3147229)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 24 august 2023 22:51:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <stdio.h>

#include <vector>

#define magic_sauce inline __attribute__((always_inline))

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

const int MAXN = 1e5;
const int MAX_AINT = 1 << 17;

std::vector<int> adj[MAXN];
int dep[MAXN];
int siz[MAXN];
int par[MAXN];

int head[MAXN];

// liniarizare heavy-first
int ord[MAXN];
int time;

int aint[2 * MAX_AINT];
int aintn;

magic_sauce void aint_update( int i, int val ){
  i += aintn - 1;
  aint[i] = val;

  while( i ){
    i = (i - 1) >> 1;
    aint[i] = max( aint[i * 2 + 1], aint[i * 2 + 2] );
  }
}

magic_sauce int aint_query( int st, int dr ){
  int ret = 0;

  st += aintn - 1;
  dr += aintn - 1;

  if( st > dr ){
    int aux = st;
    st = dr;
    dr = aux;
  }

  // stanga impara
  // dreapta para

  while( st < dr ){
    if( !(st & 1) )
      ret = max( ret, aint[st++] );
    st = (st - 1) >> 1;

    if( dr & 1 )
      ret = max( ret, aint[dr--] );
    dr = (dr - 1) >> 1;
  }

  if( st == dr )
    ret = max( ret, aint[st] );

  return ret;
}

int v[MAXN];

void init_siz( int u, int p ){
  par[u] = p;
  siz[u] = 1;

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

void init_heavy( int u, int p, int h ){
  int maxc = -1, maxs = -1;
  
  head[u] = h;

  ord[u] = time++;

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

  if( maxc < 0 )
    return;

  init_heavy( maxc, u, h );

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

int heavy_query( int a, int b ){
  int ret = 0;
  
  while( head[a] != head[b] ){
    if( dep[head[a]] > dep[head[b]] ){
      ret = max( ret, aint_query( ord[a], ord[head[a]] ) );
      a = par[head[a]];
    }else{
      ret = max( ret, aint_query( ord[b], ord[head[b]] ) );
      b = par[head[b]];
    }
  }

  ret = max( ret, aint_query( ord[a], ord[b] ) );

  return ret;
}

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

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

  fscanf( fin, "%d%d", &n, &q );
  for( i = 0 ; i < n ; i++ )
    fscanf( fin, "%d", v + i );

  for( i = 1 ; i < n ; i++ ){
    fscanf( fin, "%d%d", &a, &b );

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

  dep[0] = 0;
  init_siz( 0, 0 );
  time = 0;
  init_heavy( 0, 0, 0 );

  aintn = 1;
  while( aintn < n )
    aintn <<= 1;

  for( i = 0 ; i < n ; i++ )
    aint[aintn - 1 + ord[i]] = v[i];
  for( i = aintn - 1 ; i-- ; )
    aint[i] = max( aint[i * 2 + 1], aint[i * 2 + 2] );

  for( ; q-- ; ){
    fscanf( fin, "%d", &task );

    if( task == 0 ){
      fscanf( fin, "%d%d", &i, &a );

      aint_update( ord[i - 1], a );
    }else{
      fscanf( fin, "%d%d", &a, &b );

      fprintf( fout, "%d\n", heavy_query( a - 1, b - 1 ) );
    }
  }

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