带有lazy标记的线段树

Posted cc123321

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带有lazy标记的线段树相关的知识,希望对你有一定的参考价值。

#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,val,com,s[100000];
struct st{
    int l,r,val,add;
}tr[10000000];
void build(int l,int r,int k)
{
    tr[k].l=l;
    tr[k].r=r;
    if(l==r)
    {
        tr[k].val=s[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    tr[k].val = tr[k<<1].val + tr[k<<1|1].val;    
}
void pus(int k)
{
    int l=tr[k].l;
    int r=tr[k].r;
    tr[k].add+=tr[k>>1].add;
    tr[k].val+=(r-l+1)*tr[k>>1].add;
}
void update(int x,int y,int k,int val)
{
    if(tr[k].add)
    {
        pus(k<<1);
        pus(k<<1|1);
        tr[k].add=0;
    }
    int l=tr[k].l;
    int r=tr[k].r;
    int mid=(l+r)>>1;
    if(y<l || x>r)
        return;
    if(x<=l && r<=y)
    {
        tr[k].val += (l-r+1)*val;
        tr[k].add += val;
        return;
    }
    else 
    {
        if(x<=mid)
            update(x,y,k<<1,val);
        if(y>mid)
            update(x,y,k<<1|1,val);
        tr[k].val = tr[k<<1].val + tr[k<<1|1].val;
    }    
}
int sum(int x,int y,int k)
{
    if(tr[k].add)
    {
        pus(k<<1);
        pus(k<<1|1);
        tr[k].add=0;
    }
    int l=tr[k].l;
    int r=tr[k].r;
    int mid=(l+r)>>1;
    if(y<l || x>r)
        return 0;
    if(x<=l && r<=y)
        return tr[k].val;
    else
    {
        int ans=0;
        if(x<=mid)
            ans+=sum(x,y,k<<1);
        if(y>mid)
            ans+=sum(x,y,k<<1|1);
        return ans;
    }
}
main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&s[i]);
    build(1,n,1);
    while(m--)
    {
        scanf("%d",&com);
        if(com==1)
        {
            scanf("%d%d%d",&x,&y,&val);
            update(x,y,1,val);
        }
        else
        {
            scanf("%d%d",&x,&y);
            printf("%d\n",sum(x,y,1));
        }
    }
}

 

以上是关于带有lazy标记的线段树的主要内容,如果未能解决你的问题,请参考以下文章

线段树初步&&lazy标记

POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

算法模板——线段树之Lazy标记

HDU 1698 Just a Hook 线段树区间更新

线段树lazy标记:加乘混合

题解报告:hdu 1698 Just a Hook(线段树lazy标记的运用)