延迟修改lazy操作——线段树区间修改

一棵普通的线段树

题目链接——一棵普通的线段树

出题人明天就要半期考试了,课程是《火葬场与波》. 出题人倒在血泊中,一双有力的手摇晃着出题人的肩膀: “同志,醒醒,你还有题没出完呢”. 以下是他的遗言:

给你一个数组 A[1..n]A[1..n],初始值全为 0. 你需要写一棵裸的区间修改、区间查询的线段树, 以支持两个操作. 第一个操作是对区间 [L,R][L,R] 内的数每个数加上 vv. 第二个操作是给出区间 [L,R][L,R] 内所有数的和.

Input

第一行包含两个整数 n(1n106)n(1≤n≤106) 和 m(1m106)m(1≤m≤106), 分别是数组的大小和操作的个数.

接下来 mm 行,每行四个用空格分隔的整数 o l r v (1lrn,|v|103)o l r v (1≤l≤r≤n,|v|≤103). 如果 o=0o=0,则表示对区间 [l,r][l,r] 内每个数都加上 vv. 否则,请给出区间 [l,r][l,r] 内所有数的和,此时 v0v≡0.

Output

对于每个 o0o≠0 的操作, 输出包含一个整数的一行,表示对应区间内所有数的和.

Sample input and output

Sample Input Sample Output
5 4
0 2 4 5
1 3 5 0
0 1 3 -2
1 1 5 0
10
9
ac代码:         long long又坑了我很多发。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0x7f7f7f7f;
int n,m,t;
struct node
{
    long long  val;
    int tag;
}b[4000005];
void buildb(int l,int r,int rt)
{
    if(l==r)
    {
        b[rt].val=0;
        b[rt].tag=0;
        return ;
    }
    int mid=(l+r)>>1;
    buildb(l,mid,rt*2);
    buildb(mid+1,r,rt*2+1);
    b[rt].val=b[rt*2].val+b[rt*2+1].val;
}
void down(int l,int r,int rt)
{
    if(b[rt].tag)
    {
        int mid=(l+r)>>1;
        b[rt*2].tag+=b[rt].tag;
        b[rt*2+1].tag+=b[rt].tag;//左右子节点添加标记

        b[rt*2].val+=b[rt].tag*(mid-l+1);
        b[rt*2+1].val+=b[rt].tag*(r-mid);

        b[rt].tag=0;//清除rt的标记
    }
}
void change(int l,int r,int rt,int ll,int rr,int v)
{
    if(ll<=l&&r<=rr)
    {
        b[rt].val+=(r-l+1)*v;
        b[rt].tag+=v;        //区间刚好,给节点打上延迟标记
        return ;
    }
    down(l,r,rt);//分割区间,向下传递延迟标记
    int mid=(l+r)>>1;
    if(ll<=mid) change(l,mid,rt*2,ll,rr,v);
    if(rr>mid) change(mid+1,r,rt*2+1,ll,rr,v);
    b[rt].val=b[rt*2].val+b[rt*2+1].val;
}

long long sum(int l,int r,int rt,int ll,int rr)
{
    if(ll<=l&&r<=rr) return b[rt].val;
    down(l,r,rt);
    int mid=(l+r)>>1;
    long long  cnt=0;
    if(ll<=mid) cnt+=sum(l,mid,rt*2,ll,rr);
    if(rr>mid) cnt+=sum(mid+1,r,rt*2+1,ll,rr);
    return cnt;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int o,l,r,v;
        memset(b,0,sizeof b);
        while(m--)
        {
            scanf("%d%d%d%d",&o,&l,&r,&v);
            if(o==0)
            {
                change(1,n,1,l,r,v);
            }
            else
            {
                cout<<sum(1,n,1,l,r)<<endl;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codetypeman/article/details/81039015