Cod sursa(job #3321524)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 9 noiembrie 2025 22:50:52
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.81 kb
#include <iostream>
#include <fstream>
#include <cassert>

#include <algorithm>
#include <vector>

template<class T> using vec = std::vector<T>;

struct Splay {
  struct Node {
    int c[2] = { 0, 0 }, par = 0;
    bool flip = false;
    int key = 0, path = 0;
  };

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

  void push( int x ) {
    if( !t[x].flip ) return;
    t[x].flip = false;

    int &left = t[x].c[0], &right = t[x].c[1];
    std::swap( left, right );
    if( left ) t[left].flip ^= 1;
    if( right ) t[right].flip ^= 1;
  }

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

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

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

  void zig( int x ) {
    assert( ~side(x) );
    int y = t[x].par, sx = side(x);
    int mid = t[x].c[!sx], joe = t[y].par, sy = side(y);

    set( y, mid, sx );
    set( x, y, !sx );
    set( joe, 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 sy = side(y), sx = side(x);
      zig( x );
      zig( x );
      // ^ jur ca unul dintre astea este prost, totusi nu ma prind care...
    }
  }
};

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

  void expose( int x ) {
    int u = 0, xx = x;

    while( x ){
      splay( x );
      push( x );

      set( x, u, 1 );

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

    splay( xx ); // splay original
    push( xx );
    assert( !t[xx].c[1] );
  }

  void reroot( int x ) {
    expose( x );
    t[x].flip ^= true;
  }

  void link( int a, int b ) {
    expose( a );
    reroot( b );
    t[b].par = a;
  }

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

  void update( int x, int key ) {
    splay( x );
    t[x].key = key;
    pull( x );
  }
};

int main() {
  std::ifstream fin("heavypath.in");
  std::ofstream fout("heavypath.out");

  int n, q;
  fin >> n >> q;

  LinkCut zile(n);
  for( int i = 1; i <= n; i++ ){
    int x;
    fin >> x;
    zile.update( i, x );
  }

  for( int i = 1; i < n; i++ ){
    int a, b;
    fin >> a >> b;
    zile.link( a, b );
  }

  for( int i = 0; i < q; i++ ){
    int task, x, y;
    fin >> task >> x >> y;

    if( task == 0 )
      zile.update( x, y );
    else
      fout << zile.path_query( x, y ) << '\n';
  }

  return 0;
}