现在的位置: 首页 > 综合 > 正文

【HDU】4010 Query on The Trees 动态树之Link Cut Tree(LCT)

2017年10月16日 ⁄ 综合 ⁄ 共 2990字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.