BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊( LCT )
LCT...
----------------------------------------------------------------
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
using namespace std;
const int maxn = 200000 + 5;
const int maxnode = maxn + 100;
int n;
struct Node *pt , *null;
struct Node {
Node *ch[ 2 ] , *p , *fa;
bool rev , isRoot;
int s;
Node() {
rev = false;
isRoot = true;
s = 1;
ch[ 0 ] = ch[ 1 ] = p = fa = null;
}
inline void upd() {
s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
}
inline bool d() {
return this == p -> ch[ 1 ];
}
inline void relax() {
if( rev ) {
rev = false;
rep( i , 2 ) if( ch[ i ] != null )
ch[ i ] -> Rev();
}
}
inline void setRoot( Node* f ) {
fa = f;
p = null;
isRoot = true;
}
inline void Rev() {
rev ^= 1;
swap( ch[ 0 ] , ch[ 1 ] );
}
inline void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
void* operator new( size_t ) {
return pt++;
}
};
Node NODE[ maxnode ];
void rot( Node* t ) {
Node* p = t -> p;
p -> relax();
t -> relax();
int d = t -> d();
p -> p -> setc( t , p -> d() );
p -> setc( t -> ch[ d ^ 1 ] , d );
t -> setc( p , d ^ 1 );
p -> upd();
if( p -> isRoot ) {
p -> isRoot = false;
t -> isRoot = true;
t -> fa = p -> fa;
}
}
void splay( Node* t , Node* f = null ) {
static Node* S[ maxn ];
int top = 0;
for( Node* o = t ; o != null ; o = o -> p )
S[ ++top ] = o;
for( ; top ; top-- )
S[ top ] -> relax();
for( Node* p = t -> p ; p != f ; p = t -> p ) {
if( p -> p != f )
p -> d() != t -> d() ? rot( t ) : rot( p );
rot( t );
}
t -> upd();
}
void access( Node* t ) {
for( Node* o = null ; t != null ; o = t , t = t -> fa ) {
splay( t );
t -> ch[ 1 ] -> setRoot( t );
t -> setc( o , 1 );
}
}
Node* findRoot( Node* t ) {
access( t );
splay( t );
for( ; t -> ch[ 0 ] != null ; t = t -> ch[ 0 ] )
t -> relax();
splay( t );
return t;
}
Node* makeRoot( Node* t ) {
access( t );
splay( t );
t -> Rev();
}
void cut( Node* u , Node* v ) {
makeRoot( u );
access( v );
splay( u );
u -> setc( null , 1 );
v -> isRoot = true;
v -> fa = v -> p = null;
}
void join( Node* u , Node* v ) {
makeRoot( u );
u -> fa = v;
}
void init() {
pt = NODE;
null = new( Node );
null -> s = 0;
}
Node* V[ maxn ];
int num[ maxn ];
int main() {
freopen( "test.in" , "r" , stdin );
init();
cin >> n;
rep( i , n + 1 ) V[ i ] = new( Node );
rep( i , n ) {
scanf( "%d" , num + i );
V[ i ] -> fa = V[ min( num[ i ] + i , n ) ];
}
int m;
cin >> m;
while( m-- ) {
int x , y;
scanf( "%d%d" , &x , &y );
if( x == 1 ) {
makeRoot( V[ n ] );
access( V[ y ] );
splay( V[ y ] );
printf( "%d\n" , V[ y ] -> ch[ 0 ] -> s );
}
else {
int k;
scanf( "%d" , &k );
int d = min( num[ y ] + y , n );
num[ y ] = k;
cut( V[ y ] , V[ d ] );
join( V[ y ] , V[ min( k + y , n ) ] );
}
}
return 0;
}
----------------------------------------------------------------
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 5127 Solved: 2724
[Submit][Status][Discuss]
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input
4
1 2 1 1
3
1 1
2 1 1
1 1
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
3
HINT
Source