hdu1166-敌兵布阵(simple segment tree)

本文深入探讨了利用线段树实现高效区间操作的算法,特别关注于单点修改和区间求和操作,通过实例hdu1166-敌兵布阵来展示其应用,提供了具体的代码实现细节。
hdu1166-敌兵布阵


 线段树的操作: 建立 + 单点改变 + 区间求和 (random为区间和)
#include 
  
   
#include 
   
    
#include 
    
     
#define maxn 50005
int Num ;
int val[maxn] ;
struct line
{
    int left,right ;
    int sum ;  /**random为总和*/
}a[maxn*4];
void buil ( int l , int r , int n ) /**区间建立*/
{
    int mid ;
    a[n].left = l ;
    a[n].right = r ;
    if( l == r ) {
        a[n].sum = val[l-1] ;
        return ;
    }
    mid = ( l + r ) / 2 ;
    buil( l , mid , 2*n ) ;
    buil( mid+1 , r , 2*n+1 ) ;
    a[n].sum = a[2*n].sum + a[2*n+1].sum ;
}
void addsub( int i , int j )  
/**这次没递归,因为我只对点i一个点进行操作,那么保证二分区间里有i就可以了,没必要递归*/
{
    int ll , rr , mm, n ;
    ll = 1 ;
    rr = Num ;
    n = 1 ;
    while( ll != rr ){
/**printf( " ll rr %d %d\n",ll ,rr );*/
        if( ll <= i && i <= rr ){
            a[n].sum += j ;
            mm = ( ll + rr ) / 2 ;
            if( mm >= i ){
                rr = mm ;
                n = 2*n ;
            }
            else{
                ll = mm + 1 ;
                n = 2*n + 1 ;
            }
        }
    }
    a[n].sum += j ;
}

int quer ( int i , int j ,int start )
{
    /**这里是对一个区间操作,那么我就要二分区间判断区间的包含,所以就递归了*/
    int mid ;
    int sum = 0 ;
    if( a[start].left == i && a[start].right== j ){
        return a[start].sum ;
    }
    mid = ( a[start].left + a[start].right )/2 ;
    if( mid >= j ){
        sum += quer( i , j , 2*start ) ;
    }
    else{
        if( mid < i ){
            sum += quer( i , j , 2*start+1 ) ;
        }
        else{
            sum += quer( i , mid , 2*start ) ;
            sum += quer ( mid+1 , j , 2*start+1 ) ;
        }
    }
    return sum ;
}
int main()
{
    int T , t_ ;
    int n_ ;
    int i , j ;
    char dir[10] ;
    scanf( "%d", &T ) ;
    t_ = 0 ;
    while ( t_ < T ){
        /*t_++;*/printf( "Case %d:\n" , ++t_ ) ;
        scanf( "%d" , &Num ) ;
        n_ = 0 ;

        while( n_ < Num ){
            scanf( "%d",&val[n_ ++] ) ;
        }
        getchar() ;
        /**这个scanf的输入要灰常小心,如果前面用来scanf而且还有一些多余空格神马的输入,就要吃掉*/
        buil(1 , Num , 1) ;
        while(scanf( "%s" , dir ) && strcmp( dir , "End" ) ){
            scanf( "%d%d" , &i , &j ) ;
            getchar();
            if( !strcmp( "Query" , dir ) ){
                printf( "%d\n" , quer( i , j , 1 ) ) ;
            }
            else{
                if( !strcmp( "Add" , dir ) ){
                        addsub( i , j ) ;
                }
                else {
                    addsub( i , 0-j ) ;
                }
            }
        }
    }
    return 0;
}

    
   
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值