zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers(详细题解) 线段树

    这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的。

    此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的

    具体思路

    在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传。

    这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询。

    Inc往下带的过程也是区间分解的过程,复杂度也是O(log(n))

    明白思路就好写了。

    下面是代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <cstring>
    using namespace std;
    #define INF 0xfffffff
    #define min(a,b) (a<b?a:b)
    #define maxn 100010
    
    #define lson root<<1///左儿子 相当于 root*2
    #define rson root<<1|1///右儿子
    typedef __int64 LL;
    int n, m, val[maxn];
    
    struct node
    {
        int L, R;
        LL Sum, Inc;///Sum保存区间的和, Inc保存这个区间内所有的数字都加上Inc
        int Mid()
        {
            return (L + R)/2;
        }
    } Tree[maxn*4];
    
    void Bulid(int root,int L,int R)
    {/**递归建树,并且将值进行更新*/
        Tree[root].L = L;
        Tree[root].R = R;
        Tree[root].Sum = Tree[root].Inc = 0;
        if(L == R)
        {
            Tree[root].Sum = val[L];
            return ;
        }
        Bulid(lson, L, Tree[root].Mid() );
        Bulid(rson, Tree[root].Mid()+1, R);
        Tree[root].Sum = Tree[lson].Sum + Tree[rson].Sum;
    }
    
    void Add(int root,int L,int R,int v)
    {/**更新区间内所有的值*/
        if(L == Tree[root].L && R == Tree[root].R)
        {/**如果上述条件满足了,说明整个区间都要加上一个 v,这个时候我们只需要更新 Inc就可以了*/
            Tree[root].Inc += v;
            return ;
        }
        /**如果这个区间并不能完全更新完,则将这个值加到Sum上*/
        Tree[root].Sum += (R - L + 1)*v;
    
        /**继续向下递增*/
        if( R <= Tree[root].Mid() )
            Add(lson, L, R, v);
        else if(L > Tree[root].Mid() )
            Add(rson, L, R, v);
        else
        {
            Add(lson, L, Tree[root].Mid(), v);
            Add(rson, Tree[root].Mid()+1, R, v);
        }
    }
    
    LL QuerySum(int root,int L,int R)
    {
        LL Sum = 0;
        /**查询操作**/
        if(Tree[root].L == L && Tree[root].R == R)/**如果区间完全吻合了,可以直接算出来*/
            return  Tree[root].Inc * (R - L + 1) + Tree[root].Sum;
    
    
        /**否则我们需要向下继续更新 Inc*/
        Tree[root].Sum += Tree[root].Inc * (Tree[root].R - Tree[root].L + 1);
    
        Tree[lson].Inc += Tree[root].Inc;
        Tree[rson].Inc += Tree[root].Inc;
    
        Tree[root].Inc = 0;
        /**向下递归求和*/
        if(L > Tree[root].Mid() )
            Sum += QuerySum(rson,L,R);
        else if(R <= Tree[root].Mid() )
            Sum += QuerySum(lson,L,R);
        else
        {
            Sum += QuerySum(lson,L, Tree[root].Mid() );
            Sum += QuerySum(rson,Tree[root].Mid()+1, R);
        }
    
        return Sum;
    }
    
    int main()
    {
        int Q;
        char ch[2];
        scanf("%d %d",&n, &Q);
        Bulid(1,1,n);
        for(int i=1; i<=n; i++)
            scanf("%d",&val[i]);
        Bulid(1,1,n);
    
        while( Q-- )
        {
            int a, b, c;
            scanf("%s", ch);
    
            if(ch[0] == 'Q')
            {
                scanf("%d %d",&a, &b);
                printf("%I64d
    ", QuerySum(1,a,b) );
            }
            else
            {
                scanf("%d %d %d",&a, &b, &c);
                Add(1,a,b,c);
            }
        }
        return 0;
    }
  • 相关阅读:
    如何在Ubuntu Server 18.04上安装Microsoft的Procmon
    如何在Ubuntu 20.04上安装Wine 5.0
    如何在Kali Linux 2020中启用SSH服务
    如何在Ubuntu 20.04 LTS Focal Fossa上安装Apache Groovy
    如何使用命令在Ubuntu 20.04 Linux上安装Vmware Tools
    在Ubuntu 20.04 LTS Focal Fossa上安装Zabbix Agent
    hdu 2089 不要62
    hdu 2093 成绩排名
    hdu 2104 hide handkerchief
    leetcode147对链表进行插入排序
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/3871605.html
Copyright © 2011-2022 走看看