美文网首页信息学竞赛题解(IO题解)
BZOJ-3343: 教主的魔法(块状链套SBT)

BZOJ-3343: 教主的魔法(块状链套SBT)

作者: AmadeusChan | 来源:发表于2018-10-16 20:51 被阅读0次

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

    看到q相当小,于是就偷懒了一下,手残地写了一下块状链套SBT,复杂度各种巨大:O(q log(sqrt(n)) sqrt(n)),居然还9s+卡过去了。。。

    代码:

    #include <cstdio>
    
    #include <algorithm>
    
    #include <cstring>
    
    #include <cmath>
    
     
    
    using namespace std ;
    
     
    
    #define MAXN 2000100
    
    #define MAXB 1100
    
    #define L( t ) Left[ t ]
    
    #define R( t ) Right[ t ]
    
    #define K( t ) Key[ t ]
    
    #define S( t ) Size[ t ]
    
    #define update( t )S( t )=S(L( t ))+S(R( t ))+1
    
    #define check( ch )( ch >='0'&& ch <='9')
    
     
    
    void getint(int&t ){
    
        int ch ;for( ch =getchar(  );!check( ch ); ch =getchar(  ));
    
        t = ch -'0';
    
        for( ch =getchar(  );check( ch ); ch =getchar(  )) t *=10, t += ch -'0';
    
    }
    
     
    
    int Left[ MAXN ], Right[ MAXN ], Key[ MAXN ], Size[ MAXN ], V =0;
    
     
    
    void left(int&t ){
    
        int k =R( t );
    
        R( t )=L( k );update( t );
    
        L( k )= t ;update( k );
    
        t = k ;
    
    }
    
     
    
    void right(int&t ){
    
        int k =L( t );
    
        L( t )=R( k );update( t );
    
        R( k )= t ;update( k );
    
        t = k ;
    
    }
    
     
    
    void maintain(int&t ){
    
        if(S(L(L( t )))>S(R( t ))){
    
            right( t );
    
            maintain(R( t ));maintain( t );
    
            return;
    
        }
    
        if(S(R(R( t )))>S(L( t ))){
    
            left( t );
    
            maintain(L( t ));maintain( t );
    
            return;
    
        }
    
        if(S(R(L( t )))>S(R( t ))){
    
            left(L( t ));right( t );
    
            maintain(L( t )),maintain(R( t ));
    
            maintain( t );
    
            return;
    
        }
    
        if(S(L(R( t )))>S(L( t ))){
    
            right(R( t ));left( t );
    
            maintain(L( t )),maintain(R( t ));
    
            maintain( t );
    
            return;
    
        }
    
    }
    
     
    
    void Insert(int k ,int&t ){
    
        if(! t ){
    
            t =++ V ;
    
            L( t )=R( t )=0;
    
            S( t )=1,K( t )= k ;
    
            return;
    
        }
    
        S( t )++;
    
        Insert( k , k <K( t )?L( t ):R( t ));
    
        maintain( t );
    
    }
    
     
    
    void Delete(int k ,int&t ){
    
        if( k ==K( t )){
    
            if(!L( t )){
    
                t =R( t );return;
    
            }
    
            if(!R( t )){
    
                t =L( t );return;
    
            }
    
            right( t );Delete( k ,R( t ));
    
        }else Delete( k , k <K( t )?L( t ):R( t ));
    
        update( t );
    
        maintain( t );
    
    }
    
     
    
    int Rank(int k ,int t ){
    
        if(! t )return 0;
    
        if( k <=K( t ))return S(R( t ))+1+Rank( k ,L( t ));
    
        return Rank( k ,R( t ));
    
    }
    
     
    
    int a[ MAXN ], block[ MAXN ], head[ MAXB ], tail[ MAXB ], roof[ MAXB ], C[ MAXB ];
    
    int n , m , b =0;
    
     
    
    int Query(int l ,int r ,int c ){
    
        if( block[ l ]== block[ r ]){
    
            int x = block[ l ];
    
            if( head[ x ]== l && tail[ x ]== r )return Rank( c - C[ x ], roof[ x ]);
    
            int cnt =0;
    
            for(int i = l ; i <= r ; i ++)if( a[ i ]>= c - C[ x ]) cnt ++;
    
            return cnt ;
    
        }
    
        int cnt =Query( l , tail[ block[ l ]], c )+Query( head[ block[ r ]], r , c );
    
        for(int i = block[ l ]+1; i < block[ r ]; i ++){
    
            cnt +=Rank( c - C[ i ], roof[ i ]);
    
        }
    
        return cnt ;
    
    }
    
     
    
    void Change(int l ,int r ,int c ){
    
        if( block[ l ]== block[ r ]){
    
            int x = block[ l ];
    
            if( l == head[ x ]&& r == tail[ x ]){
    
                C[ x ]+= c ;
    
                return;
    
            }
    
            for(int i = l ; i <= r ; i ++){
    
                Delete( a[ i ], roof[ x ]);
    
                a[ i ]+= c ;
    
                Insert( a[ i ], roof[ x ]);
    
            }
    
            return;
    
        }
    
        Change( l , tail[ block[ l ]], c ),Change( head[ block[ r ]], r , c );
    
        for(int i = block[ l ]+1; i < block[ r ]; i ++){
    
            C[ i ]+= c ;
    
        }
    
    }
    
     
    
    int main(  ){
    
        memset( roof ,0,sizeof( roof ));
    
        memset( C ,0,sizeof( C ));
    
        L(0)=R(0)=S(0)=0;
    
        getint( n ),getint( m );
    
        for(int i =0; i ++< n ;)getint( a[ i ]);
    
        b =int(sqrt( n ));
    
        for(int i =0; i ++< b ;){
    
            for(int j =( i -1)* b ; j ++< i * b ;){
    
                block[ j ]= i ;
    
                Insert( a[ j ], roof[ i ]);
    
            }
    
            head[ i ]=( i -1)* b +1, tail[ i ]= i * b ;
    
        }
    
        if( b * b < n ){
    
            head[ b +1]= b * b +1, tail[ b +1]= n ;
    
            for(int i = b * b ; i ++< n ;){
    
                block[ i ]= b +1;
    
                Insert( a[ i ], roof[ b +1]);
    
            }
    
        }
    
        while( m --){
    
            int ch , l , r , c ;
    
            for( ch =getchar(  );!( ch >='A'&& ch <='Z'); ch =getchar(  ));
    
            if( ch =='M'){
    
                getint( l ),getint( r ),getint( c );
    
                Change( l , r , c );
    
            }else{
    
                getint( l ),getint( r ),getint( c );
    
                printf("%d\n",Query( l , r , c ));
    
            }
    
        }
    
        return 0;
    
    }
    

    相关文章

      网友评论

        本文标题:BZOJ-3343: 教主的魔法(块状链套SBT)

        本文链接:https://www.haomeiwen.com/subject/jyrkzftx.html