zoukankan      html  css  js  c++  java
  • 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 ;
    }
  • 相关阅读:
    聊聊mysql中的int(1)
    如何有效防止sql注入
    微信小程序WXML页面常用语法(讲解+示例)
    Spring Boot 2.x基础教程:使用集中式缓存Redis
    基于.NetCore3.1系列 —— 日志记录之自定义日志组件
    精讲RestTemplate第10篇-使用代理作为跳板发送请求
    使用Java API进行tar.gz文件及文件夹压缩解压缩
    精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证
    精讲RestTemplate第8篇-请求失败自动重试机制
    精讲RestTemplate第7篇-自定义请求失败异常处理
  • 原文地址:https://www.cnblogs.com/misty1/p/2625221.html
Copyright © 2011-2022 走看看