【SPOJ】 4155. OTOCI LCT

传送门:【SPOJ】 4155. OTOCI


题目分析:动态树果题= 3 =。。只有建边,修改单点权值,查询路径上的权值和操作。


代码如下:


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int MAXN = 30005 ;

struct Node* null ;

struct Node {
	Node* c[2] ;
	Node* f ;
	int rev ;
	int val ;
	int sum ;

	inline void newnode ( int value ) {
		c[0] = c[1] = f = null ;
		rev = 0 ;
		val = sum = value ;
	}

	inline int is_root () {
		return f == null || f->c[0] != this && f->c[1] != this ;
	}

	inline void setc ( Node* o , int d ) {
		c[d] = o ;
		o->f = this ;
	}

	inline void reverse () {
		if ( this == null ) return ;
		swap ( c[0] , c[1] ) ;
		rev ^= 1 ;
	}
	
	inline void push_up () {
		sum = c[0]->sum + val + c[1]->sum ;
	}

	inline void push_down () {
		if ( rev ) {
			c[0]->reverse () ;
			c[1]->reverse () ;
			rev = 0 ;
		}
	}

	inline void sign_down () {
		if ( !is_root () ) f->sign_down () ;
		push_down () ;
	}

	inline void zig () {
		Node* p = f ;
		Node* g = f->f ;
		p->setc ( c[1] , 0 ) ;
		if ( !p->is_root () ) g->setc ( this , g->c[1] == p ) ;
		else f = g ;
		setc ( p , 1 ) ;
		p->push_up () ;
	}

	inline void zag () {
		Node* p = f ;
		Node* g = f->f ; 
		p->setc ( c[0] , 1 ) ;
		if ( !p->is_root () ) g->setc ( this , g->c[1] == p ) ;
		else f = g ;
		setc ( p , 0 ) ;
		p->push_up () ;
	}

	inline Node* splay () {
		sign_down () ;
		while ( !is_root () ) {
			if ( f->is_root () ) {
				if ( this == f->c[0] ) zig () ;
				else zag () ;
			} else {
				if ( f == f->f->c[0] ) {
					if ( this == f->c[0] ) f->zig () , zig () ;
					else zag () , zig () ;
				} else {
					if ( this == f->c[1] ) f->zag () , zag () ;
					else zig () , zag () ;
				}
			}
		}
		push_up () ;
		return this ;
	}

	inline Node* access () {
		Node* o = this ;
		Node* x = null ;
		while ( o != null ) {
			o->splay ()->setc ( x , 1 ) ;
			o->push_up () ;
			x = o ;
			o = o->f ;
		}
		return splay () ;
	}

	inline void make_root () {
		access ()->reverse () ;
	}

	inline Node* find_root () {
		Node* o = access () ;
		while ( o->c[0] != null ) {
			o->push_down () ;
			o = o->c[0] ;
		}
		return o ;
	}

	inline void link ( Node* o ) {
		if ( o == this || find_root () == o->find_root () ) {
			printf ( "no\n" ) ;
			return ;
		}
		make_root () ;
		f = o ;
		printf ( "yes\n" ) ;
	}

	inline void change ( int value ) {
		val = value ;
		push_up () ;
		splay () ;
	}

	inline void query ( Node* o ) {
		if ( find_root () != o->find_root () ) {
			printf ( "impossible\n" ) ;
			return ;
		}
		make_root () ;
		o->access () ;
		printf ( "%d\n" , o->sum ) ;
	}
} ;

Node pool[MAXN] ;
Node* cur ;
Node* node[MAXN] ;
int n , q ;

void clear () {
	cur = pool ;
	null = cur ++ ;
	null->newnode ( 0 ) ;
}

void solve () {
	char op[20] ;
	int x , y ;
	clear () ;
	for ( int i = 1 ; i <= n ; ++ i ) {
		scanf ( "%d" , &x ) ;
		node[i] = cur ++ ;
		node[i]->newnode ( x ) ;
	}
	scanf ( "%d" , &q ) ;
	while ( q -- ) {
		scanf ( "%s%d%d" , op , &x , &y ) ;
		if ( op[0] == 'b' ) node[x]->link ( node[y] ) ;
		else if ( op[0] == 'p' ) node[x]->change ( y ) ;
		else node[x]->query ( node[y] ) ;
	}
}

int main () {
	while ( ~scanf ( "%d" , &n ) ) solve () ;
	return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值