• 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 ;
    }
  • 相关阅读:
    OC闪屏页尺寸
    OC 应用跳转QQ私聊界面或者申请加群
    一款好用的相册浏览器
    获取UILabel的numberOfLine
    一、spring入门案例
    三、为什么要配置环境变量?怎么用cmd编译运行java代码?
    十三、Swing绘图技术
    十二、泛型、反射和异常
    十一、集合框架
    十、二进制、位运算、位移运算符
  • 原文地址:https://www.cnblogs.com/misty1/p/2625221.html
Copyright © 2020-2023  润新知