BZOJ-1062: [NOI2008]糖果雨(二维树状数组)

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

首先把每个云抽象成一个点(x,y),表示该云在mod 2len意义下到达最左端的时间为x和长度为y,那么我们发现统计的时候可以补成统计两块平行四边形的点,那么坐标转一下,对于每个平行四边形,分别把坐标轴旋转45度,这样就变成了矩形,可以方便的用BIT统计了。

代码(细节超多,注意边界的重复):

#include <cstdio>

#include <algorithm>

#include <cstring>

 

using namespace std ;

 

#define REP( i , l , r ) for ( int i = l ; i <= r ; ++ i )

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

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

 

const int maxc = 1010000 ;

const int maxl = 1005 ;

 

struct BIT {

    int N , M , T[ maxl * 2 ][ maxl * 5 ] ;

    inline void Init( int _N , int _M ) {

        N = _N , M = _M ;

        rep( i , N ) rep( j , M ) T[ i ][ j ] = 0 ;

    }

    #define lowbit( x ) ( ( - x ) & x )

    inline void add( int x , int y , int v ) {

        for ( int i = x ; i <= N ; i += lowbit( i ) ) {

            for ( int j = y ; j <= M ; j += lowbit( j ) ) {

                T[ i ][ j ] += v ;

            }

        }

    }

    inline int query( int x , int y ) {

        int sum = 0 ;

        for ( int i = x ; i ; i -= lowbit( i ) ) {

            for ( int j = y ; j ; j -= lowbit( j ) ) {

                sum += T[ i ][ j ] ;

            }

        }

        return sum ;

    }

    inline int Query( int lx , int rx , int ly , int ry ) {

        if ( lx > rx || ly > ry ) return 0 ;

        int rec = query( rx , ry ) + query( lx - 1 , ly - 1 ) ;

        int ret = query( lx - 1 , ry ) + query( rx , ly - 1 ) ;

        return rec - ret ;

    }

} bit[ 2 ] ;

 

int n , len , cl[ maxc ][ 2 ] ;

 

inline void trans0( int &x , int &y ) {

    y = y - x ; x ++ , y += 3 * len ; 

}

 

inline void trans1( int &x , int &y ) {

    y = x + y ; x ++ , y += ( len + 1 ) ;

}

 

inline void change0( int x , int y , int v ) {

    trans0( x , y ) ; bit[ 0 ].add( x , y , v ) ;

}

 

inline void change1( int x , int y , int v ) {

    trans1( x , y ) ; bit[ 1 ].add( x , y , v ) ;

}

 

inline void modify( int t , int c , int l , int r , int d ) {

    int x = ( t - d * l + len * 2 ) % ( len * 2 ) ;

    int y = r - l ;

    cl[ c ][ 0 ] = x , cl[ c ][ 1 ] = y ;

    change0( x , y , 1 ) , change1( x , y , 1 ) ;

}

 

inline int query( int t , int l , int r ) {

    t %= ( len << 1 ) ;

    int ans = 0 ;

    if ( t >= r ) {

        int lx = t - r , rx = t , ly = l - r , ry = len + r ;

        trans0( lx , ly ) , trans0( rx , ry ) ;

        ans += bit[ 0 ].Query( lx , rx , ly , ry ) ;

    } else {

        int lx = 0 , rx = t , ly = l - t , ry = len + r ;

        trans0( lx , ly ) , trans0( rx , ry ) ;

        ans += bit[ 0 ].Query( lx , rx , ly , ry ) ;

        lx = 2 * len - ( r - t ) , rx = 2 * len - 1 ;

        ly = l - r , ry = len + r - t - 1 ;

        trans0( lx , ly ) , trans1( rx , ry ) ;

        ans += bit[ 0 ].Query( lx , rx , ly , ry ) ;   

    }

    if ( ! r ) return ans ;

    if ( t + r < 2 * len ) {

        int lx = t + 1 , rx = t + r , ly = l - 1 , ry = len ;

        if ( r == len ) -- rx , ++ ry ;

        trans1( lx , ly ) , trans1( rx , ry ) ;

        ans += bit[ 1 ].Query( lx , rx , ly , ry ) ;

    } else {

        int lx , rx , ly , ry ;

        if ( t + 1 < 2 * len ) {

            lx = t + 1 , rx = 2 * len - 1 ;

            ly = l - 1 , ry = r - len + t + 2 ;

            trans1( lx , ly ) , trans1( rx , ry ) ;

            ans += bit[ 1 ].Query( lx , rx , ly , ry ) ;

        }

        lx = 0 , rx = t + r - 2 * len ;

        ly = l - 2 * len + t , ry = len ;

        if ( r == len ) -- rx , ++ ry ;

        trans1( lx , ly ) , trans1( rx , ry ) ;

        ans += bit[ 1 ].Query( lx , rx , ly , ry ) ;

    }

    return ans ;

}

 

inline void Delete( int c ) {

    int x = cl[ c ][ 0 ] , y = cl[ c ][ 1 ] ;

    trans0( x , y ) ; bit[ 0 ].add( x , y , -1 ) ;

    x = cl[ c ][ 0 ] , y = cl[ c ][ 1 ] ;

    trans1( x , y ) ; bit[ 1 ].add( x , y , -1 ) ;

}

 

int main(  ) {

    scanf( "%d%d" , &n , &len ) ;

    bit[ 0 ].Init( 2 * len , 5 * len ) , bit[ 1 ].Init( 2 * len , 5 * len ) ;

    int type , t , l , r , d , c ;

    rep( i , n ) {

        scanf( "%d" , &type ) ;

        switch ( type ) {

            case 1 :

                scanf( "%d%d%d%d%d" , &t , &c , &l , &r , &d ) ; modify( t , c , l , r , d ) ;

                break ;

            case 2 :

                scanf( "%d%d%d" , &t , &l , &r ) ; printf( "%d\n" , query( t , l , r ) ) ;

                break ;

            case 3 :

                scanf( "%d%d" , &t , &c ) ; Delete( c ) ;

                break ;

        }

    }

    return 0 ;

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