hdu 5002 Tree (LCT)

hdu 5002 Tree (LCT)

几乎是模板题,维护一个最大值和次大值即可。

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define ls son[0][rt]
#define rs son[1][rt]
using namespace std ;

const int maxn = 100001 ;
const int INF = -1110011111 ;
int son[2][maxn] , mx[2][maxn] , cnt[2][maxn] , size[maxn] ;
int  fa[maxn] , is[maxn] , val[maxn] ;
int col[maxn] , add[maxn] , rev[maxn] ;
int st[55] ;
void push_up ( int rt ) {
    size[rt] = size[ls] + size[rs] + 1 ;
    st[1] = mx[0][ls] ;
    st[2] = mx[1][ls] ;
    st[3] = mx[0][rs] ;
    st[4] = mx[1][rs] ;
    st[5] = val[rt] ;
    sort ( st + 1 , st + 6 ) ;
    int T = unique ( st + 1 , st + 6 ) - st - 1 ;
    mx[0][rt] = st[T] , mx[1][rt] = st[T-1] ;
    cnt[0][rt] = cnt[1][rt] = 0 ;
    for ( int i = 0 ; i < 2 ; i ++ )
        for ( int j = 0 ; j < 2 ; j ++ ) {
            int v = mx[i][son[j][rt]] ;
            if ( v == mx[0][rt] ) cnt[0][rt] += cnt[i][son[j][rt]] ;
            if ( v == mx[1][rt] ) cnt[1][rt] += cnt[i][son[j][rt]] ;
        }
    if ( val[rt] == mx[0][rt] ) cnt[0][rt] ++ ;
    if ( val[rt] == mx[1][rt] ) cnt[1][rt] ++ ;
}

void reverse ( int rt ) {
    if ( !rt ) return ;
    swap ( son[0][rt] , son[1][rt] ) ;
    rev[rt] ^= 1 ;
}

void color ( int rt , int c ) {
    if ( !rt ) return ;
    val[rt] = c ;
    mx[0][rt] = col[rt] = c ;
    mx[1][rt] = add[rt] = INF ;
    cnt[0][rt] = size[rt] ;
    cnt[1][rt] = 0 ;
}

void ADD ( int rt , int c ) {
    if ( !rt ) return ;
    if ( add[rt] == INF ) add[rt] = c ;
    else add[rt] += c ;
    mx[0][rt] += c ;
    val[rt] += c ;
    if ( mx[1][rt] != INF ) mx[1][rt] += c ;
}

void push_down ( int rt ) {
    if ( rev[rt] ) {
        reverse ( ls ) ;
        reverse ( rs ) ;
        rev[rt] = 0 ;
    }
    if ( col[rt] != INF ) {
        color ( ls , col[rt] ) ;
        color ( rs , col[rt] ) ;
        col[rt] = INF ;
    }
    if ( add[rt] != INF ) {
        ADD ( ls , add[rt] ) ;
        ADD ( rs , add[rt] ) ;
        add[rt] = INF ;
    }
}

void down ( int rt ) {
    if ( !is[rt] ) down ( fa[rt] ) ;
    push_down ( rt ) ;
}

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

void splay ( int rt ) {
    down ( rt ) ;
    while ( !is[rt] ) {
        int y = fa[rt] , z = fa[y] ;
        if ( !is[y] ) rot ( (rt==son[0][y]) == (y==son[0][z]) ? y : rt ) ;
        rot ( rt ) ;
    }
    push_up ( rt ) ;
}

void access ( int rt ) {
    for ( int v = 0 ; rt ; rt = fa[rt] ) {
        splay ( rt ) ;
        is[rs] = 1 ; is[v] = 0 ;
        rs = v ;
        v = rt ;
        push_up ( rt ) ;
    }
}

void change_root ( int rt ) {
    access ( rt ) ;
    splay ( rt ) ;
    reverse ( rt ) ;
}

void cut ( int a , int b ) {
    change_root ( a ) ;
    access ( a ) ;
    splay ( b ) ;
    fa[b] = 0 ;
}

void link ( int a , int b ) {
	change_root ( b ) ;
	fa[b] = a ;
}

void gao1 ( int a , int b , int c , int d ) {
    cut ( a , b ) ;
    link ( c , d ) ;
}

void gao2 ( int a , int b , int c ) {
    change_root ( a ) ;
    access ( b ) ;
    splay ( b ) ;
    color ( b , c ) ;
}

void gao3 ( int a , int b , int c ) {
    change_root ( a ) ;
    access ( b ) ;
    splay ( b ) ;
    ADD ( b , c ) ;
}

void print ( int rt ) {
    if ( !rt ) return ;
    printf ( "rt = %d , mx0 = %d , mx1 = %d\n" , rt , mx[0][rt] , mx[1][rt] ) ;
    print ( ls ) ;
    print ( rs ) ;
}
void gao4 ( int a , int b ) {
    change_root ( a ) ;
    access ( b ) ;
    splay ( b ) ;
 //   print ( b ) ;
    if ( mx[1][b] == INF ) puts ( "ALL SAME" ) ;
    else printf ( "%d %d\n" , mx[1][b] , cnt[1][b] ) ;
}

void init ( int rt ) {
    int a ;
    scanf ( "%d" , &a ) ;
    val[rt] = mx[0][rt] = a ;
    mx[1][rt] = INF ;
    cnt[0][rt] = 1 ;
    cnt[1][rt] = 0 ;
    size[rt] = 1 ;
    add[rt] = col[rt] = INF ;
    son[0][rt] = son[1][rt] = fa[rt] = rev[rt] = 0 ;
    is[rt] = 1 ;
}

int main () {
    int T , ca = 0 ;
    int n , m ;
//    freopen ( "main.in" , "r" , stdin ) ;
    mx[0][0] = mx[1][0] = INF ;
    is[0] = 1 , fa[0] = 0 ;
    scanf ( "%d" , &T ) ;
    while ( T -- ) {
        scanf ( "%d%d" , &n , &m ) ;
        for ( int i = 1 ; i <= n ; i ++ )
            init ( i ) ;
        for ( int i = 1 ; i < n ; i ++ ) {
            int a , b ;
            scanf ( "%d%d" , &a , &b ) ;
			link ( a , b ) ;
        }
        printf ( "Case #%d:\n" , ++ ca ) ;
        for ( int i = 1 ; i <= m ; i ++ ) {
            int a , b , c , d ;
            scanf ( "%d" , &c ) ;
            if ( c == 1 ) {
                int f ;
                scanf ( "%d%d%d%d" , &a , &b , &d , &f ) ;
				if ( a == b || d == f ) continue ;
                gao1 ( a , b , d , f ) ;
            } else if ( c == 2 ) {
                scanf ( "%d%d%d" , &a , &b , &d ) ;
                gao2 ( a , b , d ) ;
            } else if ( c == 3 ) {
                scanf ( "%d%d%d" , &a , &b , &d ) ;
                gao3 ( a , b , d ) ;
            } else {
                scanf ( "%d%d" , &a , &b ) ;
                gao4 ( a , b ) ;
            }
        }
    }
}
/*
2
3 2
1 1 2
1 2
1 3
4 2 3
*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值