zoukankan      html  css  js  c++  java
  • 线段树-区间查询模版

    /*
    *模版原题:PKU 3468
    *线段树
    *区间求和
    */
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define LL __int64
    const int maxn = 111111;
    LL add[maxn<<2];
    LL sum[maxn<<2];
    
    
    //回溯更新父节点
    void PushUp(int rt)
    {
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    //延迟操作
    //此为成段加减算法。
    //rt为该点下标;m为该点区间范围大小
    void PushDown(int rt,int m)
    {
        if (add[rt])
        {
            //成段加,故为+=
            //同理可改为 -= max() min() change()
            add[rt<<1] += add[rt];
            add[rt<<1|1] += add[rt];
    
            sum[rt<<1] += add[rt] * (m - (m >> 1));        //    sum[rt*2]+=( add值*其旗下最终子节点个数);
            sum[rt<<1|1] += add[rt] * (m >> 1);            //  同上
            add[rt] = 0;
        }
    }
    
    //建立线段树
    //当前节点包含的范围lr;以及该节点的下标rt
    void build(int l,int r,int rt)
    {
        add[rt] = 0;        //清空操作
        if (l == r)
        {
            scanf("%lld",&sum[rt]);
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
    
        //l , m , rt << 1
        build(rson);
        PushUp(rt);
    }
    
    //成段更新
    //在L和R区间内每个数分别加上c;
    void update(int L,int R,int c,int l,int r,int rt)
    {
        if (L <= l && r <= R)                //查询
        {
            add[rt] += c;                    //储存更新操作,占时不对子节点进行操作
            sum[rt] += (LL)c * (r - l + 1);
            return ;
        }
    
        PushDown(rt , r - l + 1);    //对之前延时更新进行对应处理
        int m = (l + r) >> 1;
        if (L <= m) update(L , R , c , lson);
        if (m < R) update(L , R , c , rson);
        PushUp(rt);
    }
    
    //范围求和。
    //L 和R为输入的查询范围
    LL query(int L,int R,int l,int r,int rt)
    {
        if (L <= l && r <= R)
        {
            return sum[rt];
        }
    
        PushDown(rt , r - l + 1);
    
        int m = (l + r) >> 1;
        LL ret = 0;
        if (L <= m) ret += query(L , R , lson);
        if (m < R) ret += query(L , R , rson);
        return ret;
    }
    
    int main()
    {
        int N , Q;
        scanf("%d%d",&N,&Q);
        build(1 , N , 1);
        while (Q--)
        {
            char s[2];
            int a , b , c;
            scanf("%s",s);
            if (s[0] == 'Q')
            {
                scanf("%d%d",&a,&b);
                printf("%lld
    ",query(a , b , 1 , N , 1));
            }
    
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                update(a , b , c , 1 , N , 1);
            }
        }
        return 0;
    }
  • 相关阅读:
    正则
    在开发过程中调试报表插件详细教程
    在开发过程中调试报表插件详细教程
    页面导出Excel文件总结
    java.lang.IllegalArgumentException: sheetName '' is invalid
    java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Map
    表达式中的一些常用模式.
    C++使用libcurl做HttpClient
    C++ curl跨平台HttpClient
    java.lang.NumberFormatException: empty String
  • 原文地址:https://www.cnblogs.com/mochenmochen/p/5156775.html
Copyright © 2011-2022 走看看