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

hdu 1754 I Hate It (splay tree伸展树)

2013年01月03日 ⁄ 综合 ⁄ 共 2020字 ⁄ 字号 评论关闭

hdu 1754 I Hate It

其实我只是来存一下我的splay模板的。。请大牛们多多指教

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std ;

const int maxn = 222222 ;

int son[2][maxn] , col[maxn] , fa[maxn] , size[maxn] , val[maxn] ;
int tot ;
int num[maxn] ;

void new_node () {
	size[tot] = 1 ;
	fa[tot] = son[0][tot] = son[1][tot] = -1 ;
	val[tot] = col[tot] = 0 ;
	tot ++ ;
}

void update ( int rt ) {
	size[rt] = 1 ;
	col[rt] = val[rt] ;
	if ( son[0][rt] != -1 ) 
		size[rt] += size[son[0][rt]] , col[rt] = max ( col[rt] , col[son[0][rt]] ) ;
	if ( son[1][rt] != -1 )
		size[rt] += size[son[1][rt]] , col[rt] = max ( col[rt] , col[son[1][rt]] ) ;
}

int build ( int l , int r ) {
	if ( l > r ) return -1 ;
	int mid = ( l + r ) >> 1 ;
	new_node () ;
	int temp = tot - 1 ;
	val[temp] = num[mid] ;
	son[0][temp] = build ( l , mid - 1 ) ;  
	if ( son[0][temp] != -1 ) fa[son[0][temp]] = temp ;
	son[1][temp] = build ( mid + 1 , r ) ;
	if ( son[1][temp] != -1 ) fa[son[1][temp]] = temp ;
	update ( temp ) ;
	return temp ;
}

void rot ( int rt , int c ) {
	int y = fa[rt] , z = fa[y] ;
	son[!c][y] = son[c][rt] ;
	if ( son[c][rt] != -1 ) fa[son[c][rt]] = y ;
	fa[rt] = z ;
	if ( z != -1 ) {
		if ( y == son[0][z] ) son[0][z] = rt ;
		else son[1][z] = rt ;
	}
	son[c][rt] = y , fa[y] = rt ;
	update ( y ) ;
}

void splay ( int rt , int to ) {
	while ( fa[rt] != to ) {
		if ( fa[fa[rt]] == to ) {
			if ( rt == son[0][fa[rt]] ) rot ( rt , 1 ) ;
			else rot ( rt , 0 ) ;
		}
		else {
			int y = fa[rt] , z = fa[y] ;
			if ( rt == son[0][y] ) {
				if ( y == son[0][z] ) rot ( y , 1 ) , rot ( rt , 1 ) ;
				else rot ( rt , 1 ) , rot ( rt , 0 ) ;
			}
			else {
				if ( y == son[1][z] ) rot ( y , 0 ) , rot ( rt , 0 ) ;
				else rot ( rt , 0 ) , rot ( rt , 1 ) ;
			}
		}
	}
	update ( rt ) ;
	/*为什么只要在最后更新rt节点呢?因为在旋转的过程中,fa[rt]总是旋到rt下面的
	所以在旋转的时候,我们不断的更新fa[rt],而不需要一直更新rt,只要在splay之后更新rt就好了
	*/
}

int find ( int rt , int key ) {
	int cnt = 0 ;
	if ( son[0][rt] != -1 ) cnt = size[son[0][rt]] ;
	if ( cnt + 1 == key ) return rt ;
	if ( cnt >= key ) return find ( son[0][rt] , key ) ;
	return find ( son[1][rt] , key - cnt - 1 ) ;
}

int main () {
	int n , m , i , j , k , a , b ;
	char op[11] ;
	while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
		for ( i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &num[i] ) ;
		tot = 0 ;
		int root = build ( 0 , n + 1 ) , temp ;
		while ( m -- ) {
			scanf ( "%s%d%d" , op , &a , &b ) ;
			a ++ , b ++ ;//因为建树的时候,把0也建进去了,但实际上0是不在原数组中的,所有往后推移一位
			if ( op[0] == 'U' ) {
				temp = find ( root , a ) ;
				splay ( temp , -1 ) ;
				root = temp ;
				val[root] = b - 1 ;
			//	update ( root ) ;
			//这里为什么不用更新rt呢?因为对于size的值是不会变的,而val值已经更新了,而对于col值,下次是splay时,肯定会更新掉的
			}
			else {
				temp = find ( root , a - 1 ) ;
				splay ( temp , -1 ) ;
				root = temp ;
				temp = find ( root , b + 1 ) ;
				splay ( temp , root ) ;
				printf ( "%d\n" , col[son[0][temp]] ) ;
			}
		}
	}
}

抱歉!评论已关闭.