Cod sursa(job #3293244)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 10 aprilie 2025 22:29:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.98 kb
#include <stdio.h>
#include <assert.h>

#include <vector>
#include <algorithm>

struct Splay {
  struct Node {
    int c[2], par;
    int flip;
    int key, max;
    Node(): par(0), flip(false), key(0), max(0) { c[0] = c[1] = 0; }
  };

  std::vector<Node> t;
  Splay( int n ): t(n + 1) {}

  void push_flip( int x ) {
    if( !x ) return;
    t[x].flip ^= 1;
  }

  void push( int x ) {
    if( !t[x].flip ) return;
    std::swap( t[x].c[0], t[x].c[1] );
    t[x].flip = false;
    push_flip( t[x].c[0] );
    push_flip( t[x].c[1] );
  }

  void pull( int x ) {
    int left = t[x].c[0], right = t[x].c[1];
    t[x].max = t[x].key;
    if( left ) t[x].max = std::max( t[x].max, t[left].max );
    if( right ) t[x].max = std::max( t[x].max, t[right].max );
  }

  int side( int x ) {
    int par = t[x].par;
    if( t[par].c[0] == x ) return 0;
    if( t[par].c[1] == x ) return 1;
    return -1;
  }

  void link( int x, int y, int side ) {
    if( y ) t[y].par = x;
    if( x && ~side ){
      t[x].c[side] = y;
      pull( x );
    }
  }

  void zig( int x ) {
    int y = t[x].par, sx = side( x );
    int up = t[y].par, sy = side( y ), mij = t[x].c[!sx];

    link( y, mij, sx );
    link( x, y, !sx );
    link( up, x, sy );
  }

  void splay( int x ) {
    while( ~side( x ) ){
      int y = t[x].par;
      if( !~side( y ) ){
        push( y );
        push( x );
        zig( x );
        continue;
      }

      int z = t[y].par;
      push( z );
      push( y );
      push( x );

      int sx = side( x ), sy = side( y );
      zig( sx == sy ? y : x );
      zig( x );
    }
  }
};

struct LinkCut : Splay {
  LinkCut( int n ): Splay(n) {}

  void expose( int uu ) {
    int u = uu, prev = 0;
    while( u ) {
      splay( u );
      push( u );

      t[u].c[1] = prev;
      pull( u );

      prev = u;
      u = t[u].par;
    }

    splay( uu );
  }

  void reroot( int u ) {
    expose( u );
    push_flip( u );
  }

  void Link( int a, int b ) {
    expose( a );
    reroot( b );
    // assert( side( a ) == -1 );
    // assert( side( b ) == -1 );
    t[b].par = a; // soft link
  }

  int Path( int a, int b ) {
    reroot( a );
    expose( b );
    return t[b].max;
  }

  void Update( int u, int newv ) {
    expose( u );
    t[u].key = newv;
    pull( u );
  }
};

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

  int n, m;
  fscanf( fin, "%d%d", &n, &m );

  LinkCut zile(n);
  for( int u = 1; u <= n; u++ ){
    int x;
    fscanf( fin, "%d", &x );
    zile.Update( u, x );
  }

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

  for( int i = 0; i < m; i++ ){
    int task;
    fscanf( fin, "%d", &task );

    if( task == 0 ){
      int u, newv;
      fscanf( fin, "%d%d", &u, &newv );
      zile.Update( u, newv );
    }else{// if( task == 1 ){
      int a, b;
      fscanf( fin, "%d%d", &a, &b );
      fprintf( fout, "%d\n", zile.Path( a, b ) );
    }
  }

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