传送门:【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 ; }