BZOJ-1493: [NOI2007]项链工厂(线段树)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1493

差点被BZOJ上坑爹的剧透骗去写又长又丑的splay(虽然splay明显可写。。。),这题由于珠子的相对位置不变,所以可以用线段树维护,然后弄个delta维护一下在F过偶数次情况下的偏移量,dir维护F过的奇偶性,然后分类讨论就可以弄出对应左边在原项链中的位置,然后对于后面几个区间的操作注意顺逆时针的情况讨论,然后细节很多,写的时候多多注意。

代码(调了两个小时,尼玛要是在NOI赛场上怎么办啊。。。):

#include <cstdio>

#include <cstring>

 

#define rep( i , x ) for ( int i = 0 ; i ++ < x ; )

#define REP( i , a , b ) for ( int i = a ; i <= b ; ++ i )

 

#define left( t ) t -> left

#define right( t ) t -> right

#define L( t ) t -> l

#define R( t  ) t -> r

#define lc( t ) t -> lc

#define rc( t ) t -> rc

#define C( t ) t -> c

#define T( t ) t -> tag

 

int ch ;

 

void getint( int &t ) {

    for ( ch = getchar(  ) ; ch < '0' || ch > '9' ; ch = getchar(  ) ) ;

    t = ch - '0' ;

    for ( ch = getchar(  ) ; ch >= '0' && ch <= '9' ; ch = getchar(  ) ) t = 10 * t + ch - '0' ;

}

 

const int maxn = 501000 , maxv = 1510000 ;

 

inline void upd( int &x , int &y , int &z , int a , int b , int c ) {

    z += c , z -= ( y == a ) ;

    y = b ;

}

 

struct node {

 

    node *left , *right ;

    int l , r , lc , rc , c , tag ;

 

    inline void pushdown(  ) {

        if ( tag ) {

            lc = rc = tag , c = 1 ;

            if ( l < r ) left -> tag = tag , right -> tag = tag ;

            tag = 0 ;

        }

    }

 

    inline void update(  ) {

        upd( lc = left -> lc , rc = left -> rc , c = left -> c , right -> lc , right -> rc , right -> c ) ;

    }

 

} sgt[ maxv ] ;

 

typedef node* np ;

 

np pt = sgt , root ;

 

int n , c , col[ maxn ] , m ;

 

void build( int l , int r , np &t ) {

    t = pt ++ ;

    L( t ) = l , R( t ) = r , T( t ) = 0 ;

    if ( l == r ) {

        lc( t ) = rc( t ) = col[ l ] , C( t ) = 1 ;

        return ;

    }

    int mid = ( l + r ) >> 1 ;

    build( l , mid , left( t ) ) , build( mid + 1 , r , right( t ) ) ;

    t -> update(  ) ;

}

 

void change( int l , int r , int c , np t ) {

    if ( l == L( t ) && r == R( t ) ) {

        T( t ) = c ; return ;

    }

    t -> pushdown(  ) ;

    int mid = ( L( t ) + R( t ) ) >> 1 ;

    if ( r <= mid ) change( l , r , c , left( t ) ) ; else

        if ( l > mid ) change( l , r , c , right( t ) ) ; else {

            change( l , mid , c , left( t ) ) , change( mid + 1 , r , c , right( t ) ) ;

        }

    left( t ) -> pushdown(  ) , right( t ) -> pushdown(  ) ; t -> update(  ) ;

}

 

void query( int l , int r , int &x , int &y , int &z , np t ) {

    t -> pushdown(  ) ;

    if ( l == L( t ) && r == R( t ) ) {

        x = lc( t ) , y = rc( t ) , z = C( t ) ;

        return ;

    }

    int mid = ( L( t ) + R( t ) ) >> 1 ;

    if ( r <= mid ) query( l , r , x , y , z , left( t ) ) ; else

        if ( l > mid ) query( l , r , x , y , z , right( t ) ) ; else {

            int a , b , c ;

            query( l , mid , x , y , z , left( t ) ) , query( mid + 1 , r , a , b , c , right( t ) ) ;

            upd( x , y , z , a , b , c ) ;

        }

}

 

int getcol( int pos , np t ) {

    t -> pushdown(  ) ;

    if ( L( t ) == R( t ) ) return lc( t ) ;

    int mid = ( L( t ) + R( t ) ) >> 1 ;

    return getcol( pos , pos <= mid ? left( t ) : right( t ) ) ;

}

 

int delta = 0 , dir = 1 ;

 

inline void trans( int &pos ) {

    if ( dir == 1 || pos == 1 ) {

        pos -= delta ;

        if ( pos <= 0 ) pos += n ;

    } else {

        pos = n - pos + 2 - delta ;

        while ( pos <= 0 ) pos += n ;

        while ( pos > n ) pos -= n ;

    }

}

 

char s[ 10 ] ;

 

int main(  ) {

    getint( n ) , getint( c ) ;

    rep( i , n ) getint( col[ i ] ) ;

    build( 1 , n , root ) ;

    getint( m ) ;

    int x , y , z , a , b , c , i , j , k ;

    while ( m -- ) {

        scanf( "%s" , s ) ;

        if ( s[ 0 ] == 'R' ) {

            getint( a ) ;

            delta = ( delta + a * dir + n ) % n ;

        } else if ( s[ 0 ] == 'F' ) {

            dir *= - 1 ;

        } else if ( s[ 0 ] == 'S' ) {

            getint( x ) , getint( y ) ;

            trans( x ) , trans( y ) ;

            a = getcol( x , root ) , b = getcol( y , root ) ;

            change( x , x , b , root ) , change( y , y , a , root ) ;

        } else if ( s[ 0 ] == 'P' ) {

            getint( x ) , getint( y ) , getint( z ) ;

            trans( x ) , trans( y ) ;

            if ( x < y ) {

                if ( dir == 1 ) change( x , y , z , root ) ; else {

                    change( 1 , x , z , root ) , change( y , n , z , root ) ;

                }

            } else if ( x > y ) {

                if ( dir == - 1 ) change( y , x , z , root ) ; else {

                    change( 1 , y , z , root ) , change( x , n , z , root ) ;

                }

            } else change( x , x , z , root ) ;

        } else if ( strlen( s ) == 1 ) {

            query( 1 , n , x , y , z , root ) ;

            if ( z == 1 ) printf( "%d\n" , 1 ) ; else printf( "%d\n" , z - ( x == y ) ) ;

        } else {

            getint( x ) , getint( y ) ;

            trans( x ) , trans( y ) ;

            if ( x < y ) {

                if ( dir == 1 ) query( x , y , a , b , c , root ) ; else {

                    query( y , n , a , b , c , root ) , query( 1 , x , i , j , k , root ) ;

                    upd( a , b , c , i , j , k ) ;

                }

            } else if ( x > y ) {

                if ( dir == - 1 ) query( y , x , a , b , c , root ) ; else {

                    query( x , n , a , b , c , root ) , query( 1 , y , i , j , k , root ) ;

                    upd( a , b , c , i , j , k ) ;

                }

            } else {

                query( x , x , a , b , c , root ) ;

            }

            printf( "%d\n" , c ) ;

        }

    }

    return 0 ;

}
    原文作者:AmadeusChan
    原文地址: https://www.jianshu.com/p/735274e0419f#comments
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞