• 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 " , 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 MB
    Submit: 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

    Sample Output

    2
    3

    HINT

    Source

  • 相关阅读:
    微信菜单设置为小程序报错85005错误
    VS2013常用快捷键
    VS2017专业版和企业版激活密钥
    微信小程序image组件binderror使用例子(对应html、js中的onerror)
    本科无学位有哪些途径来获得硕士学位
    asp.net 微信JsSDK
    使用nginx反向代理,一个80端口下,配置多个微信项目
    对称与非对称加密;SSL;HTTPS;AJP
    java 在实例化异常的时候做的事情
    简单理解正向,反向,透明代理
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4596405.html
Copyright © 2020-2023  润新知