Cod sursa(job #3283603)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 9 martie 2025 23:12:18
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.82 kb
#include <stdio.h>

#include <algorithm>
#include <vector>

struct Splay {
  struct Node {
    int c[2], par;
    int key, max;
    bool flip;

    Node(): par(0), key(-1), max(-1), flip(false) { c[0] = c[1] = 0; }
  };

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

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

  void push( int u ) {
    if( !t[u].flip ) return;

    std::swap( t[u].c[0], t[u].c[1] );
    t[u].flip = false;
    
    push_flip( t[u].c[0] );
    push_flip( t[u].c[1] );
  }

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

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

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

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

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

  void splay( int x ) {
    while( side( x ) >= 0 ){
      int y = t[x].par;
      if( side( y ) < 0 ){
        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 );

      // castram
      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 );
    t[b].par = a; // weak link, no need to pull
    // pull( a );
  }

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

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

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

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

  LinkCut zile(n);
  for( int i = 1; i <= n; i++ ){
    int x;
    fscanf( fin, "%d", &x );
    zile.Update( i, 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 < q; i++ ){
    int task, x, y;
    fscanf( fin, "%d%d%d", &task, &x, &y );

    if( task == 0 )
      zile.Update( x, y );
    else
      fprintf( fout, "%d\n", zile.Path( x, y ) );
  }

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