• POJ


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

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

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

    2、线段树单点更新太费时,所以使用区间更新

    3、

    #include <cstdio>
    
    #define L(root) ((root) << 1)
    #define R(root) (((root) << 1) + 1)
    
    const int MAXN = 100001;
    int numbers[MAXN];
    
    struct st
    {
        // 区间范围
        int left, right;
        // 更新值、区间总和
        long long delta, sum;
    } st[MAXN * 4];
    
    // 建树代码基本不变
    void build(int root, int l, int r)
    {
        st[root].left = l, st[root].right = r, st[root].delta = 0;
        if (l == r)
        {
            st[root].sum = numbers[l];
            return;
        }
    
        int m = l + ((r - l) >> 1);
        build(L(root), l, m);
        build(R(root), m + 1, r);
        st[root].sum = st[L(root)].sum + st[R(root)].sum;
    }
    
    long long query(int root, int l, int r)
    {
        // 如查询区间恰等于节点区间,直接返回该区间总和即可
        if (st[root].left == l && st[root].right == r)
        {
            return st[root].sum;
        }
    
        // 否则需将当前区间的“缓冲”值更新下去并修正各节点区间的总和
        if (st[root].delta)
        {
            st[L(root)].delta += st[root].delta;
            st[R(root)].delta += st[root].delta;
            st[L(root)].sum += st[root].delta * (st[L(root)].right - st[L(root)].left + 1);
            st[R(root)].sum += st[root].delta * (st[R(root)].right - st[R(root)].left + 1);
            st[root].delta = 0;
        }
    
        int m = st[root].left + ((st[root].right - st[root].left) >> 1);
        if (r <= m)
        {
            return query(L(root), l, r);
        }
        else if (l > m)
        {
            return query(R(root), l, r);
        }
        else
        {
            return query(L(root), l, m) + query(R(root), m + 1, r);
        }
    }
    
    void update(int root, int l, int r, long long v)
    {
        // 如变更区间恰等于节点区间,只修正当前节点区间即可
        if (st[root].left == l && st[root].right == r)
        {
            st[root].delta += v;
            st[root].sum += v * (r - l + 1);
            return;
        }
    
        // 否则需向下修正相关节点区间
        if (st[root].delta)
        {
            st[L(root)].delta += st[root].delta;
            st[R(root)].delta += st[root].delta;
            st[L(root)].sum += st[root].delta * (st[L(root)].right - st[L(root)].left + 1);
            st[R(root)].sum += st[root].delta * (st[R(root)].right - st[R(root)].left + 1);
            st[root].delta = 0;
        }
    
        int m = st[root].left + ((st[root].right - st[root].left) >> 1);
        if (r <= m)
        {
            update(L(root), l, r, v);
        }
        else if (l > m)
        {
            update(R(root), l, r, v);
        }
        else
        {
            update(L(root), l, m, v);
            update(R(root), m + 1, r, v);
        }
        // 同时一定要记得修正当前节点区间的总和
        st[root].sum = st[L(root)].sum + st[R(root)].sum;
    }
    
    int main()
    {
        int N, Q;
        while (scanf("%d%d", &N, &Q) != EOF)
        {
            for (int i = 1; i <= N; ++i)
            {
                scanf("%d", &numbers[i]);
            }
    
            build(1, 1, N);
    
            char cmd;
            int l, r;
            long long v;
            while (Q--)
            {
                scanf(" %c", &cmd);
                scanf("%d%d", &l, &r);
                switch (cmd)
                {
                case 'Q':
                    printf("%lld
    ", query(1, l, r));
                    break;
    
                case 'C':
                    scanf("%lld", &v);
                    if (v)
                    {
                        update(1, l, r, v);
                    }
                    break;
                }
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    上篇用到的matcher函数
    lambdaj学习
    Redis高级应用——2
    Redis入门
    从gitee 下载代码到本地
    CSS中对图片(background)的一些设置心得总结
    nodejs 安装Ionic 和cordova
    Spring MVC内容协商机制详解
    基于Servlet3.0的编程式SpringMVC实例详解
    基于Junit的Spring集成测试方法
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4957239.html
Copyright © 2020-2023  润新知