线段树模板1

题目链接:https://www.luogu.org/problemnew/show/P3372

要注意的是线段树结点数组的大小应为4*n,而不是2*n。

#include<cstdio>
using namespace std;
typedef long long LL;

const int maxn=100005;

struct node{
    int l,r;
    LL value,add;
}tr[4*maxn];    //注意这里是4倍

int n,m;
LL a[maxn],ans;

void build(int v,int l,int r){  //建立线段树
    tr[v].l=l,tr[v].r=r,tr[v].add=0;
    if(l==r){
        tr[v].value=a[r];
        return;
    }
    int mid=(l+r)>>1;
    build(2*v,l,mid);
    build(2*v+1,mid+1,r);
    tr[v].value=tr[2*v].value+tr[2*v+1].value;
}

void spread(int v){   //传递增量
    tr[2*v].value+=tr[v].add*(tr[2*v].r-tr[2*v].l+1); 
    tr[2*v+1].value+=tr[v].add*(tr[2*v+1].r-tr[2*v+1].l+1);
    tr[2*v].add+=tr[v].add;
    tr[2*v+1].add+=tr[v].add;
    tr[v].add=0;
}

void update(int v,int l,int r,LL k){   //更新
    if(tr[v].l==l&&tr[v].r==r){
        tr[v].value+=k*(r-l+1);
        tr[v].add+=k;
        return;
    }
    if(tr[v].add) spread(v);
    int mid=(tr[v].l+tr[v].r)>>1;
    if(r<=mid){
        update(2*v,l,r,k);
    }
    else{
        if(l>mid){
            update(2*v+1,l,r,k);
        }
        else{
            update(2*v,l,mid,k);
            update(2*v+1,mid+1,r,k);
        }
    }
    tr[v].value=tr[2*v].value+tr[2*v+1].value;
}

void query(int v,int l,int r){     //查询
    if(tr[v].l==l&&tr[v].r==r){
        ans+=tr[v].value;
        return;
    }
    if(tr[v].add) spread(v);
    int mid=(tr[v].l+tr[v].r)>>1;
    if(r<=mid){
        query(2*v,l,r);
    }
    else{
        if(l>mid){
            query(2*v+1,l,r);
        }
        else{
            query(2*v,l,mid);
            query(2*v+1,mid+1,r);
        }
    }
    tr[v].value=tr[2*v].value+tr[2*v+1].value;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    build(1,1,n);
    while(m--){
        int op;
        scanf("%d",&op);
        if(op==1){
            int x,y;
            LL k;
            scanf("%d%d%lld",&x,&y,&k);
            update(1,x,y,k);
        }
        else{
            int x,y;
            scanf("%d%d",&x,&y);
            ans=0;
            query(1,x,y);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2019-04-25 20:17  Frank__Chen  阅读(194)  评论(0编辑  收藏  举报