poj 3468 -- A Simple Problem with Integers ( 线段树 , 段更新 , 段求和 )

区间更新查询线段树
本文介绍了一种使用线段树实现区间更新和查询的方法,包括数据结构定义、核心算法如构建、更新和查询等,并通过一个具体示例展示了如何进行区间范围内的数值更新和求和操作。
# include <cstdio>
# include <iostream>
# include <set>
# include <map>
# include <vector>
# include <list>
# include <queue>
# include <stack>
# include <cstring>
# include <string>
# include <cstdlib>
# include <cmath>
# include <algorithm>

using namespace std ;

const int maxn = 110000 ;
long long summ ;

struct Tree
{
    long long sum ;
    long long flag ;
} tree [ maxn * 4 ] ;

void pushup ( int pos )
{
    tree [ pos ] . sum = tree [ pos * 2 ] . sum + tree [ pos * 2 + 1 ] . sum ;
}

void pushdown ( int l , int r , int pos )
{
    int m = ( l + r ) / 2 ;
    long long val = tree [ pos ] . flag ;
    tree [ pos ] . flag = 0 ;
    tree [ pos * 2 ] . sum += ( m - l + 1 ) * val ;
    tree [ pos * 2 + 1 ] . sum += ( r - m ) * val ;
    tree [ pos * 2 ] . flag += val ;
    tree [ pos * 2 + 1 ] . flag += val ;
}

void build ( int l , int r , int pos )
{
    if ( l == r )
    {
        scanf ( "%lld" , & tree [ pos ] . sum ) ;
        return ;
    }
    int m = ( l + r ) / 2 ;
    build ( l , m , pos * 2 ) ;
    build ( m + 1 , r , pos * 2 + 1 ) ;
    pushup ( pos ) ;
}

void update ( int l , int r , int pos , int L , int R , long long val )
{
    if ( l >= L && r <= R )
    {
        tree [ pos ] . flag += val ;
        tree [ pos ] . sum += val * ( r - l + 1 ) ;
        return ;
    }
    if ( tree [ pos ] . flag )
        pushdown ( l , r , pos ) ;
    int m = ( l + r ) / 2 ;
    if ( m >= L )
        update ( l , m , pos * 2 , L , R , val ) ;
    if ( m + 1 <= R )
        update ( m + 1 , r , pos * 2 + 1 , L , R , val ) ;
    pushup ( pos ) ;
}

void quer ( int l , int r , int pos , int L , int R )
{
    if ( l >= L && r <= R )
    {
        summ += tree [ pos ] . sum ;
        return ;
    }
    if ( tree [ pos ] . flag )
        pushdown ( l , r , pos ) ;
    int m = ( l + r ) / 2 ;
    if ( m >= L )
        quer ( l , m , pos * 2 , L , R ) ;
    if ( m + 1 <= R )
        quer ( m + 1 , r , pos * 2 + 1 , L , R ) ;
}

int main ( )
{
    int n , q ;
    scanf ( "%d%d" , & n , & q ) ;
    build ( 1 , n , 1 ) ;
    getchar ( ) ;
    while ( q -- )
    {
        char c ;
        c = getchar ( ) ;
        if ( c == 'Q' )
        {
            int a , b ;
            scanf ( "%d%d" , & a , & b ) ;
            summ = 0 ;
            quer ( 1 , n , 1 , a , b ) ;
            printf ( "%lld\n" , summ ) ;
        }
        else
        {
            int a , b ;
            long long c ;
            scanf ( "%d%d%lld" , & a , & b , & c ) ;
            update ( 1 , n , 1 , a , b , c ) ;
        }
        getchar ( ) ;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值