【数据结构】线段树 (区间修改/区间求和)

时间:2020-03-19 19:19:04   收藏:0   阅读:52

【本文解决 区间修改/区间求和 的问题】



区间求和部分内容与上一篇内容相同,详见 线段树点修改/区间求和


已经知道了在O(logN)的复杂度内求N个连续数之和的做法

对于区间修改,最简单的办法就是进行多次点修改

但是多次点修改最后的时间复杂度为O(NlogN),还不及最普通的数组模拟O(n)效率高

并且,多次点修改的操作与用树状数组模拟几乎无差别,甚至说树状数组写起来要比线段树简单得多

所以对于区间修改,要引入一种叫做“懒惰标记”的概念



struct node
{
    int l,r;
    ll sum,lazy;
    void add(ll x)
    {
        sum+=x*(r-l+1);
        lazy+=x;
    }
}tree[MAXN*4];









#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN=1e5+50;

struct node
{
    int l,r;
    ll sum,lazy;
    void add(ll x)
    {
        sum+=x*(r-l+1);
        lazy+=x;
    }
}tree[MAXN*4];

int ar[MAXN];

void push_up(int id)
{
    tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}

void push_down(int id)
{
    tree[id<<1].add(tree[id].lazy);
    tree[id<<1|1].add(tree[id].lazy);
    tree[id].lazy=0;
}

void buildTree(int id,int l,int r)
{
    tree[id].l=l;
    tree[id].r=r;
    tree[id].sum=tree[id].lazy=0;
    if(l==r)
        tree[id].sum=ar[l];
    else
    {
        int mid=(l+r)>>1;
        buildTree(id<<1,l,mid);
        buildTree(id<<1|1,mid+1,r);
        push_up(id);
    }
}

void update(int id,int l,int r,ll val)
{
    int L=tree[id].l,R=tree[id].r;
    if(l<=L&&R<=r)
        tree[id].add(val);
    else
    {
        push_down(id);
        int mid=(L+R)>>1;
        if(mid>=l)
            update(id<<1,l,r,val);
        if(mid<r)
            update(id<<1|1,l,r,val);
        push_up(id);
    }
}

ll query(int id,int l,int r)
{
    int L=tree[id].l,R=tree[id].r;
    if(l<=L&&R<=r)
        return tree[id].sum;
    push_down(id);
    int mid=(L+R)>>1;
    ll res=0;
    if(mid>=l)
        res+=query(id<<1,l,r);
    if(mid<r)
        res+=query(id<<1|1,l,r);
    push_up(id);
    return res;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int i,n,q,a,b,d;
    char opr[5];
    cin>>n>>q;
    for(i=1;i<=n;i++)
        cin>>ar[i];
    buildTree(1,1,n);
    while(q--)
    {
        cin>>opr;
        if(opr[0]=='Q')
        {
            cin>>a>>b;
            cout<<query(1,a,b)<<'\n';
        }
        else
        {
            cin>>a>>b>>d;
            update(1,a,b,d);
        }
    }
    
    return 0;
}

原文:https://www.cnblogs.com/stelayuri/p/12526469.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!