• 线段树的区间更新---A Simple Problem with Integers


    POJ   3468

    Description

    给出了一个序列,你需要处理如下两种询问。

    "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。

    "Q a b" 询问[a, b]区间中所有值的和。

    Input

    第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

    第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

    接下来Q行询问,格式如题目描述。

    Output

    对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4

    Sample Output

    4
    55
    9
    15

    思路:线段树区间更新。

    本题代码是很好的线段树区间更新模板:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define LL long long
    using namespace std;
    const int maxn=100005;
    struct Node
    {
        LL sum,val;
    } node[4*maxn];
    
    void pushup(int i)
    {
        node[i].sum=node[i<<1].sum+node[i<<1|1].sum;
    }
    
    void pushdown(int i,int m)
    {
        if(node[i].val)
        {
            node[i<<1].val+=node[i].val;
            node[i<<1|1].val+=node[i].val;
            node[i<<1].sum+=(LL)node[i].val*(m-(m>>1));
            node[i<<1|1].sum+=(LL)node[i].val*(m>>1);
            node[i].val=0;
        }
    }
    
    void build(int l,int r,int i)
    {
        node[i].val=0;
        if(l==r)
        {
            scanf("%I64d",&node[i].sum);
            return ;
        }
        int mid=(l+r)/2;
        build(l,mid,i<<1);
        build(mid+1,r,i<<1|1);
        pushup(i);
    }
    
    LL query(int L,int R,int l,int r,int i)
    {
       if(L<=l&&r<=R)
        {
            return node[i].sum;
        }
        int mid=(l+r)>>1;
        pushdown(i,r-l+1);
        LL ans=0;
        if(L<=mid)ans+=query(L,R,l,mid,i<<1);
        if(mid<R)ans+=query(L,R,mid+1,r,i<<1|1);
        pushup(i);
        return ans;
    }
    
    void update(int L,int R,int add,int l,int r,int i)
    {
         if(L<=l&&r<=R)
        {
            node[i].sum+=(LL)add*(r-l+1);
            node[i].val+=add;
            return ;
        }
        pushdown(i,r-l+1);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,add,l,mid,i<<1);
        if(mid<R)update(L,R,add,mid+1,r,i<<1|1);
        pushup(i);
    }
    
    int main()
    {
        int n,q,a,b;
        LL c;
        while(scanf("%d%d",&n,&q)!=EOF)
        {
            build(1,n,1);
            char s[3];
            while(q--)
            {
                scanf("%s",s);
                if(s[0]=='C')
                {
                    scanf("%d%d%I64d",&a,&b,&c);
                    update(a,b,c,1,n,1);
                }
                else if(s[0]=='Q')
                {
                    scanf("%d%d",&a,&b);
                    printf("%I64d
    ",query(a,b,1,n,1));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    ArcGIS Engine 笔记-控件类型
    个人简历(公开版)
    生活垃圾处理相关
    如何让nextcloud支持avi文件在线播放
    NextCloud前端支持播放mov文件
    使用Huginn抓取Discourse论坛
    使用WordPress制作微信小程序
    Github 快速建库上传本地代码
    BestSync多终端文件资料同步利器
    ABAP-SAP HANA 数据库并发控制
  • 原文地址:https://www.cnblogs.com/chen9510/p/5383423.html
Copyright © 2020-2023  润新知