传送门:【HDU】4010 Query on The Trees
题目分析:感动了T U T~~~~第一道动态树(模板题),当我提交的第一发就是PE的时候我差点感动的哭了。
为了巩固代码,我于是删了重敲了一遍,这次一遍AC~
在国庆期间我会总结一下自己的所学,包括动态树,这几天我也会多多研究一下这个神奇的算法~
总觉得学了不总结是很不对的事情,还是多多总结的好~
在我学习动态树的过程,在群上问了大神们很多问题,也很感激大神们的热情与无私,在他们的教授下我对于动态树也算是初步的了解了,在此谢谢那些回答我问题的大神们~
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define clr( a , x ) memset ( a , x , sizeof a )
typedef long long LL ;
const int MAXN = 300005 ;
const int INF = 0x3f3f3f3f ;
struct Node* null ;
struct Node {
Node* f ;
Node* c[2] ;
int maxv ;
int addv ;
int flip ;
int v ;
void newnode ( int val = 0 ) {
flip = 0 ;
maxv = v = val ;
f = c[0] = c[1] = null ;
}
void add_val ( int val ) {
if ( this == null ) return ;
maxv += val ;
addv += val ;
v += val ;
}
void reverse () {
if ( this == null ) return ;
std :: swap ( c[0] , c[1] ) ;
flip ^= 1 ;
}
void link_child ( Node* o , int d ) {
c[d] = o ;
o->f = this ;
}
void push_up () {
maxv = std :: max ( c[0]->maxv , c[1]->maxv ) ;
maxv = std :: max ( v , maxv ) ;
}
void push_down () {
if ( addv ) {
c[0]->add_val ( addv ) ;
c[1]->add_val ( addv ) ;
addv = 0 ;
}
if ( flip ) {
c[0]->reverse () ;
c[1]->reverse () ;
flip = 0 ;
}
}
void all_down () {
if ( !is_root () ) f->all_down () ;
push_down () ;
}
int is_root () {
return f == null || f->c[0] != this && f->c[1] != this ;
}
void rotate ( int d ) {
Node* p = f ;
Node* gp = p->f ;
p->link_child ( c[d] , !d ) ;
if ( !p->is_root () ) {
if ( p == gp->c[0] ) gp->link_child ( this , 0 ) ;
else gp->link_child ( this , 1 ) ;
} else f = gp ;
link_child ( p , d ) ;
p->push_up () ;
}
void splay () {
all_down () ;
while ( !is_root () ) {
if ( f->is_root () ) {
if ( this == f->c[0] ) rotate ( 1 ) ;
else rotate ( 0 ) ;
} else {
if ( f == f->f->c[0] ) {
if ( this == f->c[0] ) f->rotate ( 1 ) , rotate ( 1 ) ;
else rotate ( 0 ) , rotate ( 1 ) ;
} else {
if ( this == f->c[1] ) f->rotate ( 0 ) , rotate ( 0 ) ;
else rotate ( 1 ) , rotate ( 0 ) ;
}
}
}
push_up () ;
}
void access () {
Node* o = this ;
Node* x = null ;
while ( o != null ) {
o->splay () ;
o->link_child ( x , 1 ) ;
o->push_up () ;
x = o ;
o = o->f ;
}
splay () ;
}
Node* find_root () {
access () ;
Node* o = this ;
while ( o->c[0] != null ) {
o->push_down () ;
o = o->c[0] ;
}
return o ;
}
void make_root () {
access () ;
reverse () ;
}
void cut () {
access () ;
c[0]->f = null ;
c[0] = null ;
push_up () ;
}
void link ( Node* o ) {
if ( this == o || find_root () == o->find_root () ) {
printf ( "-1\n" ) ;
return ;
}
make_root () ;
f = o ;
}
void cut ( Node* o ) {
if ( this == o || find_root () != o->find_root () ) {
printf ( "-1\n" ) ;
return ;
}
make_root () ;
o->cut () ;
}
void add ( Node* o , int val ) {
if ( find_root () != o->find_root () ) {
printf ( "-1\n" ) ;
return ;
}
make_root () ;
o->access () ;
o->add_val ( val ) ;
}
int query ( Node* o ) {
if ( find_root () != o->find_root () ) return -1 ;
make_root () ;
o->access () ;
return o->maxv ;
}
} ;
struct Edge {
int u , v ;
} E[MAXN] ;
Node memory_pool[MAXN] ;
Node* cur ;
Node* node[MAXN] ;
int n , q ;
void clear () {
cur = memory_pool ;
null = cur ++ ;
null->newnode ( -INF ) ;
}
void solve () {
int op , val , x , y ;
clear () ;
rep ( i , 1 , n ) scanf ( "%d%d" , &E[i].u , &E[i].v ) ;
For ( i , 1 , n ) {
scanf ( "%d" , &val ) ;
node[i] = cur ++ ;
node[i]->newnode ( val ) ;
}
rep ( i , 1 , n ) node[E[i].u]->link ( node[E[i].v] ) ;
scanf ( "%d" , &q ) ;
while ( q -- ) {
scanf ( "%d" , &op ) ;
if ( op == 1 ) {
scanf ( "%d%d" , &x , &y ) ;
node[x]->link ( node[y] ) ;
} else if ( op == 2 ) {
scanf ( "%d%d" , &x , &y ) ;
node[x]->cut ( node[y] ) ;
} else if ( op == 3 ) {
scanf ( "%d%d%d" , &val , &x , &y ) ;
node[x]->add ( node[y] , val ) ;
} else {
scanf ( "%d%d" , &x , &y ) ;
printf ( "%d\n" , node[x]->query ( node[y] ) ) ;
}
}
printf ( "\n" ) ;
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}