信息学竞赛题解(IO题解)

BZOJ-3211: 花神游历各国(线段树)

2018-10-16  本文已影响0人  AmadeusChan

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

上帝造题的七分钟2那道题完全一样,就不多说了。。。练手题。。。期末考快到了,是不是该滚去学习了。。。

代码:

d1160924ab18972b3ae7c5ace4cd7b899f510af3.jpg.png
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
 
using namespace std ;
 
#define MAXN 100100
#define L( t ) ( t << 1 ) 
#define R( t ) ( ( t << 1 ) ^ 1 )
#define update( t ) S[ t ] = S[ L( t ) ] + S[ R( t ) ] , flag[ t ] = flag[ L( t ) ] & flag[ R( t ) ]
#define check( ch ) ( ch >= '0' && ch <= '9' )
#define mid( l , r ) ( ( l + r ) >> 1 )
#define ll long long
 
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' ;
}
 
void putint( ll t ) {
    if ( ! t ) putchar( '0' ) ; else {
        int ans[ 40 ] ; ans[ 0 ] = 0 ;
        for ( ; t ; t /= 10 ) ans[ ++ ans[ 0 ] ] = t % 10 ;
        for ( int i = ans[ 0 ] ; i ; -- i ) putchar( '0' + ans[ i ] ) ;
    }
    putchar( '\n' ) ;
}
 
int left[ MAXN * 4 ] , right[ MAXN * 4 ] , a[ MAXN ] , n , m ;
ll S[ MAXN * 4 ] ;
bool flag[ MAXN * 4 ] ;
 
void build( int l , int r , int t ) {
    left[ t ] = l , right[ t ] = r ;
    if ( l == r ) {
        S[ t ] = a[ l ] , flag[ t ] = a[ l ] <= 1 ;
        return ;
    }
    build( l , mid( l , r ) , L( t ) ) , build( mid( l , r ) + 1 , r , R( t ) ) ;
    update( t ) ;
}
 
void change( int l , int r , int t ) {
    if ( flag[ t ] ) return ;
    if ( left[ t ] == right[ t ] ) {
        S[ t ] = int( sqrt( S[ t ] ) ) ;
        flag[ t ] = S[ t ] <= 1 ;
        return ;
    }
    if ( r <= mid( left[ t ] , right[ t ] ) ) change( l , r , L( t ) ) ; else
    if ( l > mid( left[ t ] , right[ t ] ) ) change( l , r , R( t ) ) ; else {
        change( l , mid( left[ t ] , right[ t ] ) , L( t ) ) , change( mid( left[ t ] , right[ t ] ) + 1 , r , R( t ) ) ;
    }
    update( t ) ;
}
 
ll sum( int l , int r , int t ) {
    if ( l == left[ t ] && r == right[ t ] ) return S[ t ] ;
    if ( r <= mid( left[ t ] , right[ t ] ) ) return sum( l , r , L( t ) ) ; else
    if ( l > mid( left[ t ] , right[ t ] ) ) return sum( l , r , R( t ) ) ; else
    return sum( l , mid( left[ t ] , right[ t ] ) , L( t ) ) + sum( mid( left[ t ] , right[ t ] ) + 1 , r , R( t ) ) ;
}
 
int main(  ) {
    getint( n ) ; for ( int i = 0 ; i ++ < n ; ) getint( a[ i ] ) ;
    build( 1 , n , 1 ) ;
    getint( m ) ;
    while ( m -- ) {
        int x , l , r ; getint( x ) , getint( l ) , getint( r ) ;
        if ( x == 1 ) putint( sum( l , r , 1 ) ) ; else change( l , r , 1 ) ;
    }
    return 0 ; 
}

上一篇下一篇

猜你喜欢

热点阅读