题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2002
每个点只会跳到另外一个确切的点,这跟树中每个节点只有一个父节点一样的,那么按照这个规律建树即可,然后LCT维护,对于每个查询,ACCESS(V),然后输出sizeleft[v]即可。
代码:
# include <cstdio>
# include <algorithm>
# include <cstring>
using namespace std ;
# define MAXN 200010
# define L( t ) left[ t ]
# define R( t ) right[ t ]
# define F( t ) father[ t ]
# define G( t )F(F( t ) )
# define S( t ) size[ t ]
# define P( t ) parent[path_roof( t ) ]
# define update( t )S( t ) =S(L( t ) ) +S(R( t ) ) + 1
# define C( t ) (L(F( t ) ) == t )
# define clear( t )memset( t , 0 , sizeof( t ) )
int left[ MAXN ] , right[ MAXN ] , father[ MAXN ] , parent[ MAXN ] , size[ MAXN ] ;
void zag( int t ) {
int k =R( t ) , u =F( t ) ;
bool flag =C( t ) ;
R( t ) =L( k ) ;F(L( k ) ) = t ;update( t ) ;
L( k ) = t ;F( t ) = k ; update( k ) ;
F( k ) = u ; if ( u ) if ( flag )L( u ) = k ; else R( u ) = k ;
}
void zig( int t ) {
int k =L( t ) , u =F( t ) ;
bool flag =C( t ) ;
L( t ) =R( k ) ;F(R( k ) ) = t;update( t ) ;
R( k ) = t ;F( t ) = k ; update( k ) ;
F( k ) = u ; if ( u ) if ( flag )L( u ) = k ; else R( u ) = k ;
}
void splay( int t ) {
while (F( t ) ) {
if ( !G( t ) ) if (C( t ) )zig(F( t ) ) ; else zag(F( t ) )
; else {
if (C( t ) ) {
if (C(F( t ) ) )zig(G( t ) ) ;
zig(F( t ) ) ;
} else {
if ( !C(F( t ) ) )zag(G( t ) ) ;
zag(F( t ) ) ;
}
}
}
}
int path_roof( int t ) {
splay( t ) ;
while (L( t ) ) t =L( t ) ;
return t ;
}
void Access( int t ) {
int v = 0 ;
do {
splay( t ) ;
F(R( t ) ) = 0 ;P(R( t ) ) = t ;R( t ) = v ;F( v ) = t ;update( t ) ;
v = t ; t =P( t ) ;
} while ( t ) ;
}
void Make_tree( int t ) {
L( t ) =R( t ) =F( t ) = parent[ t ] = 0 ;
S( t ) = 1 ;
}
void Cut( int t ) {
Access( t ) ;splay( t ) ;
F(L( t ) ) = 0 ;L( t ) = 0 ;P( t ) = 0 ;update( t ) ;
}
void Join( int t , int v ) {
P( t ) = v ;
Access( t ) ;
}
void Init( ) {
F( 0 ) =L( 0 ) =R( 0 ) =S( 0 ) = 0;
clear( parent ) ;
}
int k[ MAXN ] , n , m ;
int main ( ) {
Init( ) ;
scanf( "%d" , &n ) ;
for ( int i = 0 ; i ++ < n + 1 ; )Make_tree( i ) ;
for ( int i = 0 ; i ++ < n ; ) {
scanf( "%d" , &k[ i ] ) ;
Join( i ,min( n + 1 , i + k[ i ] ) ) ;
}
scanf( "%d" , &m ) ;
while ( m -- ) {
int x ;
scanf( "%d" , &x ) ;
if ( x == 1 ) {
int y ;
scanf( "%d" , &y ) ; y ++ ;
Access( y ) ;splay( y ) ;
printf( "%d\n" ,S(L( y ) ) ) ;
} else {
int y , z ;
scanf( "%d%d" , &y , &z ) ; y ++ ;
Cut( y ) ;Join( y ,min( y + z , n + 1 ) ) ;
}
}
return 0 ;
}