poj 3468 A Simple Problem with Integers(线段树)

题意:N个数字,Q个操作,Q表示询问[s,t]中的数据和,C表示从s到t中的每个数据都加上x;

思路:简单的线段树,把每一段放入和存入结构体中,但是如果每次更新都更新到叶子节点的话,会超时,因此在结构体中加入一个标记,记录每个区间的增加量,这样不用再更新到叶子节点,当查询的时候加上即可。

代码:

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
#define N 100004
using namespace std ;

typedef __int64 lx ;

struct node
{
    int ll , rr ;
    lx ss , v ;//ss表示区间和,v 表示区间增量
}p[4*N] ;

lx dat[N] ;
int n , m ;

//建树
void built( int id , int l , int r )
{
    p[id].ll = l ;
    p[id].rr = r ;
    p[id].v = 0 ;
    if ( l == r )
    {
        p[id].ss = dat[l] ;
        return ;
    }
    else
    {
        int mid = ( l + r )/ 2 ;
        built( 2*id , l , mid );
        built( 2*id+1 , mid+1 , r );
    }
    p[id].ss = p[2*id].ss + p[2*id+1].ss ;
}

//询问
lx query( int id , int l , int r )
{
    if( p[id].ll == l && p[id].rr == r )//如果查到这个区间,将区间和加上增量返回
    {
        return ( p[id].ss + ( r - l + 1 ) * p[id].v );
    }
    else//否则的话,将这个区间的增量加到子节点上。
    {
        p[2*id].v += p[id].v ;
        p[2*id+1].v += p[id].v ;
        p[id].ss += ( p[id].rr - p[id].ll + 1 ) * p[id].v ;
        p[id].v = 0 ;
    }
    int mid = ( p[id].ll + p[id].rr ) /2 ;
    if ( l > mid )
    return query( 2*id+1 , l , r );
    else if ( r <= mid )
    return query ( 2*id , l , r );
    else
    {
        return query( 2 * id , l , mid ) + query( 2 * id + 1 , mid + 1 , r );
    }
}

//更新
void update( int id , int l , int r , lx v )
{
    //找到要更新区间,将这个区间增量加上,然后返回,不必到叶子节点
    if ( p[id].ll == l && p[id].rr == r )
    {
        p[id].v += v ;
        return ;
    }
    p[id].ss += ( r - l + 1 ) * v ;
    int mid = ( p[id].ll + p[id].rr ) / 2 ;
    if ( l > mid )
    update( 2*id+1 , l , r , v );
    else if ( r <= mid )
    update( 2*id , l , r , v );
    else
    {
        update( 2*id , l , mid , v );
        update( 2*id+1 , mid +1  , r , v );
    }

    //p[id].ss = p[2*id].ss + p[2*id+1].ss ;
}

int main()
{
    int i , x , y ;
    lx v ;
    char c ;

    while( scanf( "%d%d" , &n , &m ) != EOF )
    {
        for ( i = 1 ; i <= n ; i++ )
        scanf( "%I64d" , &dat[i] );
        built( 1 , 1 , n );
        while( m-- )
        {
            getchar();
            scanf( "%c%d%d" , &c , &x , &y );
            if ( c == 'Q' )
            {
                lx sx = query( 1 , x , y );
                cout<<sx<<endl;
            }
            else
            {
                scanf( "%I64d" , &v );
                update( 1 , x , y , v );
            }
        }
    }
    return 0 ;
}
posted @ 2012-08-06 15:11  Misty_1  阅读(151)  评论(0编辑  收藏  举报