洛谷P3372 【模板】线段树 1

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m;
struct SegmentTree {
    int l,r;
    ll sum,lazy;//区间和 lazy标记 
#define l(p) (node[p].l)
#define r(p) (node[p].r)
#define sum(p) (node[p].sum)
#define lazy(p) (node[p].lazy)
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
} node[maxn*4];
void build(int p,int l,int r) {//传入结点编号p和对应区间[l,r] 
    l(p)=l;r(p)=r;
    if(l==r) {//叶节点 
        scanf("%lld",&sum(p));
        return;
    }
    int mid=l+r>>1;
    build(ls(p),l,mid);//递归建左右子树 
    build(rs(p),mid+1,r);
    sum(p)=sum(ls(p))+sum(rs(p));//更新区间和 
}
void update(int p,ll val) {//对p结点的值增加val 
    sum(p)+=(r(p)-l(p)+1)*val;
    lazy(p)+=val;
}
void pushdown(int p) {//下放标记 
    if(lazy(p)==0) return;//有标记才下放 
    update(ls(p),lazy(p));//传至左右子树 
    update(rs(p),lazy(p));
    lazy(p)=0;//清空自身标记 
}
void change(int p,int L,int R,ll val) {//区间修改 [L,R]增加val 
    if(l(p)>R||r(p)<L) return;//无交集 
    if(L<=l(p)&&R>=r(p)) return update(p,val);//该节点被完全覆盖 
    pushdown(p);//下放 
    change(ls(p),L,R,val);//递归修改 
    change(rs(p),L,R,val);
    sum(p)=sum(ls(p))+sum(rs(p));//更新信息 
}
ll query(int p,int L,int R) {
    if(l(p)>R||r(p)<L) return 0;//无交集 
    if(L<=l(p)&&R>=r(p)) return sum(p);//被完全覆盖 
    pushdown(p);//下放 
    return query(ls(p),L,R)+query(rs(p),L,R);//左右子树和 
}
int main() {
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--) {
        int flag,l,r,val;
        scanf("%d",&flag);
        if(flag==1) scanf("%d%d%d",&l,&r,&val),change(1,l,r,val);
        else scanf("%d%d",&l,&r),printf("%lld\n",query(1,l,r));
    }
    return 0;
}
posted @ 2019-03-31 20:17  宇興  阅读(122)  评论(0编辑  收藏  举报