Pagini recente » Cod sursa (job #2199326) | Cod sursa (job #1904893) | Cod sursa (job #2918891) | Cod sursa (job #2476616) | Cod sursa (job #3321524)
#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;
}