Luogu P3372 【模板】线段树 1

  终于再过线段树。

  参考可禾大神的线段树,然后在down的时候把 add[root*2]+=add[root] 打成了 add[root+2]+=add[root]; 调了一个下午,还被嘲讽。

  对于区间修改主要用的是Lazy Tag,把增量延迟下方。

  可以达到O(nlogn)。

  这次代码里有注释。

#include<cstdio>
using namespace std;
typedef long long LL;
const int N=100005;
LL seg[N*4+10],add[N*4+10],a[N],n,q,x,y,z,c,i;
inline void read(LL &x)
{
    x=0; char ch=getchar(); int flag=1;
    while (ch<'0'||ch>'9') { if (ch=='0') flag=-1; ch=getchar(); }
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    x*=flag;
}
inline void write(LL x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline void up(LL root) { seg[root]=seg[root*2]+seg[root*2+1]; } //向上传递信息 
inline void down(LL root,LL l,LL r) //延迟标记下传 
{
    if (add[root])
    {
        add[root*2]+=add[root];
        add[root*2+1]+=add[root];
        seg[root*2]+=add[root]*l;
        seg[root*2+1]+=add[root]*r;
        add[root]=0;
    }
}
inline void build(LL root,LL l,LL r) //递归建边,注意要向上传递 
{
    if (l==r) seg[root]=a[l]; else
    {
        LL mid=l+r>>1;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
        up(root);
    }
}
inline LL query(LL root,LL l,LL r,LL ql,LL qr) //区间求和,标记下传!!! 
{
    if (l>=ql&&r<=qr) return seg[root];
    else
    {
        LL mid=l+r>>1;
        down(root,mid-l+1,r-mid);
        LL res=0;
        if (ql<=mid) res+=query(root*2,l,mid,ql,qr);
        if (mid<qr) res+=query(root*2+1,mid+1,r,ql,qr);
        return res;
    }
}
inline void change(LL root,LL l,LL r,LL ql,LL qr,LL v) //区间修改,线段树的核心,注意修改之后既会影响到它的父节点,也影响到它的儿子 
{
    if (l>=ql&&r<=qr)
    {
        seg[root]+=(r-l+1)*v;
        add[root]+=v;
    } else 
    {
        LL mid=l+r>>1;
        down(root,mid-l+1,r-mid);
        if (ql<=mid) change(root*2,l,mid,ql,qr,v);
        if (mid<qr) change(root*2+1,mid+1,r,ql,qr,v);
        up(root);
    }
}
int main()
{
    read(n); read(q);
    for (i=1;i<=n;++i)
    read(a[i]);
    build(1,1,n);
    while (q--)
    {
        read(c);
        if (c==1) { read(x); read(y); read(z); change(1,1,n,x,y,z); } else
        { read(x); read(y); write(query(1,1,n,x,y)); putchar('
'); }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/cjjsb/p/7966117.html