luogu_P3372 【模板】线段树 1

https://www.luogu.org/problem/P2824

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数加上x

2.求出某区间每一个数的和

输入格式

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入 #1
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出 #1
11
8
20

说明/提示

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^,保证在int64/long long数据范围内)

样例说明:


延迟标记:该节点的值已修改,但其左右子节点尚未更新。

#include<iostream>
#include<cstdio>

#define ri register int
#define u long long

namespace opt {

    inline u in() {
        u x(0),f(1);
        char s(getchar());
        while(s<'0'||s>'9') {
            if(s=='-') f=-1;
            s=getchar();
        }
        while(s>='0'&&s<='9') {
            x=(x<<1)+(x<<3)+s-'0';
            s=getchar();
        }
        return x*f;
    }

}

using opt::in;

#define NN 100005

namespace xds {

    struct node {
        u l,r,sum,add;
    } a[NN<<2];

    u b[NN];

    void build(const u &rt,const u &l,const u &r) {
        a[rt].l=l,a[rt].r=r;
        if(l==r) {
            a[rt].sum=b[l];
            return;
        }
        u mid(l+r>>1),_x(rt<<1),_y(rt<<1|1);
        build(_x,l,mid);
        build(_y,mid+1,r);
        a[rt].sum=a[_x].sum+a[_y].sum;
    }

    void pushdown(const u &rt) {
        if(a[rt].add) {
            u _x(rt<<1),_y(rt<<1|1);
            a[_x].sum+=(a[_x].r-a[_x].l+1)*a[rt].add;
            a[_y].sum+=(a[_y].r-a[_y].l+1)*a[rt].add;
            a[_x].add+=a[rt].add,a[_y].add+=a[rt].add;
            a[rt].add=0;
        }
    }

    void update(const u &rt,const u &l,const u &r,const u &x) {
        if(a[rt].l>=l&&a[rt].r<=r) {
            a[rt].sum+=(a[rt].r-a[rt].l+1)*x;
            a[rt].add+=x;
            return;
        }
        pushdown(rt);
        u _x(rt<<1),_y(rt<<1|1);
        if(l<=a[_x].r) update(_x,l,r,x);
        if(r>=a[_y].l) update(_y,l,r,x);
        a[rt].sum=a[_x].sum+a[_y].sum;
    }

    u query(const u &rt,const u &l,const u &r) {
        if(a[rt].l>=l&&a[rt].r<=r) return a[rt].sum;
        pushdown(rt);
        u _x(rt<<1),_y(rt<<1|1),_re(0);
        if(l<=a[_x].r) _re+=query(_x,l,r);
        if(r>=a[_y].l) _re+=query(_y,l,r);
        return _re;
    }

}

namespace mainstay {

    inline void solve() {
        u N(in()),M(in());
        for(ri i(1); i<=N; ++i) xds::b[i]=in();
        xds::build(1,1,N);
        for(ri i(1); i<=M; ++i) {
            u k(in());
            if(k==1) {
                u l(in()),r(in()),_x(in());
                xds::update(1,l,r,_x);
            } else {
                u l(in()),r(in());
                printf("%lld
",xds::query(1,l,r));
            }
        }
    }

}

int main() {

    //freopen("x.txt","r",stdin);
    std::ios::sync_with_stdio(false);
    mainstay::solve();

}
原文地址:https://www.cnblogs.com/ling-zhi/p/11776954.html