线段树lazy操作

本人自己出的一道题:

已知有N个数,其中第i个数的只是a[i],对这i个数进行q个操作,每次先输入op,代表操作,若op==0,则输入x,y,求a[x]+......+a[y]的值。若op==1则 输入x,y,z,将a[x]......a[y]之间的每一个(包括a[x],a[y])加z。先输入n,q(n<=300000,q<=300000)
接下来一行n个数,其中第i个数表示a[i]。接下来q行,先输入操作op,然后在对应地输入若op=0,则输出这个和,不然对应地进行操作。并且输出是一行一个数     (z<=10000000)

样例输入:

10 6
1 2 3 4 5 6 7 8 9 10
1 1 5 -5
1 2 3 -6
1 2 5 5 
1 2 5 8
1 4 9 -6
0 2 7

样例输出:23

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int N=(1<<19)+10; 
int l[N<<1],r[N<<1];
long long sum[N<<1],lazy[N<<1];//lazy也可以写成add 
int q,op,x,y,z,n;
long long v[N],ans;
void build(){//建树 
    int s=1;
    while(s<=n)s*=2;
    for(int i=s*2-1;i>=s;i--){
        l[i]=r[i]=i-s+1;
        sum[i]=v[i-s+1];lazy[i]=0;
    }
    for(int i=s-1;i>=1;i--){
        lazy[i]=0;
        l[i]=l[i*2];r[i]=r[i*2+1];
        sum[i]=sum[i*2+1]+sum[i*2];
    }
}



void pushdown(int i){//下方操作,将当前的lazy下放 
    if(lazy[i]){//这样下放,保证每次修改都能有效的进行 
        lazy[2*i]+=lazy[i];lazy[2*i+1]+=lazy[i];
        sum[2*i]+=(r[2*i]-l[2*i]+1)*lazy[i];
        sum[2*i+1]+=(r[2*i+1]-l[2*i+1]+1)*lazy[i];
        lazy[i]=0;
    }
}




void update(int l1,int r1,int i,int k){//更新操作,每次不要忘记下放 
    if(l1<=l[i]&&r[i]<=r1){
        lazy[i]+=k;
        sum[i]+=(r[i]-l[i]+1)*k;
        return ;
    }
    int mid=(l[i]+r[i])/2;
    pushdown(i);
    if(l1>mid)update(l1,r1,i*2+1,k);
    else if(r1<=mid)update(l1,r1,i*2,k);
    else {
        update(l1,mid,i*2,k);
        update(mid+1,r1,i*2+1,k);
    }
    sum[i]=sum[i*2]+sum[i*2+1];
}
void ask(int l1,int r1,int i){//询问操作,每次不要忘记下放 
    if(l1<=l[i]&&r[i]<=r1){
        ans+=sum[i];
        return ;
    }
    pushdown(i);
    int mid=(l[i]+r[i])/2;
    if(l1>mid)ask(l1,r1,i*2+1);
    else if(r1<=mid)ask(l1,r1,i*2);
    else {
        ask(l1,mid,i*2);
        ask(mid+1,r1,i*2+1);
    }
}




int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
    build();
    for(int i=1;i<=q;i++){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%d",&x,&y,&z);
            update(x,y,1,z);
        }
        else {
            scanf("%d%d",&x,&y);
            ans=0;ask(x,y,1);
            printf("%d
",ans);
        }
    }
}
原文地址:https://www.cnblogs.com/c201904xyorz/p/9990779.html