• 1082 线段树练习 3 (线段树区间修改+区间求和)


    题目描述 Description

    给你N个数,有两种操作:


    1:给区间[a,b]的所有数增加X


    2:询问区间[a,b]的数的和。

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,

    再接下来一个正整数Q,每行表示操作的个数,

    如果第一个数是1,后接3个正整数,

    表示在区间[a,b]内每个数增加X,如果是2,

    表示操作2询问区间[a,b]的和是多少。

    pascal选手请不要使用readln读入

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

    3

    1

    2

    3

    2

    1 2 3 2

    2 2 3

    样例输出 Sample Output

    9

    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=200000

    1<=q<=200000

     
    思路:
    算是模板提吧,没什么难点,好久没写线段树了,写下熟悉下线段树区间操作,之前还有点不懂,后面自己独立写出来了感觉对这个的理解还是上升了。
     
    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    const int M = 2e5 + 10;
    ll lazy[M<<2],sum[M<<2];
    void pushup(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void pushdown(int rt,int m){
        if(lazy[rt]){
            lazy[rt<<1] += lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            sum[rt<<1] += lazy[rt]*(m-(m>>1));
            sum[rt<<1|1] += lazy[rt]*(m>>1);
            lazy[rt] = 0;
        }
    }
    
    void build(int l,int r,int rt){
        lazy[rt] = 0;
        if(l == r){
            cin>>sum[rt];
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int L,int R,int c,int l,int r,int rt){
        if(L <= l&&R >= r){
            lazy[rt] += c;
            sum[rt] += (r - l + 1)*c;
            return ;
        }
        pushdown(rt,r - l + 1);
        int m = (l + r) >> 1;
        if(L <= m) update(L,R,c,lson);
        if(R > m) update(L,R,c,rson);
        pushup(rt);
    }
    
    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(R > m) ret += query(L,R,rson);
        return ret;
    }
    
    int main()
    {
        int n,q,x,l,r,c;
        cin>>n;
        build(1,n,1);
        cin>>q;
        while(q--){
            cin>>x;
            if(x == 1){
                cin>>l>>r>>c;
                update(l,r,c,1,n,1);
            }
            else{
                cin>>l>>r;
                cout<<query(l,r,1,n,1)<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    【扩展】1. PHP 大括号{} 的使用
    preg_replace 中修正符 e 的解析
    terminal 修改终端显示的名字
    find 命令详解
    OSI 7层结构 粗认识
    vi 全解析
    awk 学习笔记
    scp 复制远程文件 文件带空格 处理
    更新博客地址啦!!!
    ubuntu16.04安装NVIDIA驱动遇到的问题
  • 原文地址:https://www.cnblogs.com/kls123/p/8563162.html
Copyright © 2020-2023  润新知