线段树单点|区间更新模板

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const int maxn=50010;
int a[maxn],ans[maxn],lazy[maxn];

void pushup(int rt)//1.更新节点信息
{
    ans[rt]=ans[rt<<1]+ans[rt<<1|1];
}

void build(int l,int r,int rt) //2.建树
{
    if(l==r)
    {
        ans[rt]=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}

void pushdown(int rt,int ln,int rn)//3.ln表示左子树元素结点个数,rn表示右子树结点个数
{
    if(lazy[rt])
    {
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        ans[rt<<1]+=lazy[rt]*ln;
        ans[rt<<1|1]+=lazy[rt]*rn;
        lazy[rt]=0;
    }
}

void add(int L,int c,int l,int r,int rt) //4.点更新
{
    if(l==r)
    {
        ans[rt]+=c;
        return ;
    }
    int mid=(l+r)>>1;
    if(L<=mid) add(L,c,l,mid,rt<<1);
    else add(L,c,mid+1,r,rt<<1|1);
}

void update(int L,int R,int c,int l,int r,int rt)//5.区间更新
{
    if(L<=l&&r<=R)
    {
        ans[rt]+=c*(r-l+1);
        lazy[rt]+=c;
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    if(L<mid) update(L,R,c,l,mid,rt<<1);
    if(R>mid) update(L,R,c,mid+1,r,rt<<1|1);
    pushup(rt);
}

ll query(int L,int R,int l,int r,int rt)//6.区间更新
{
    if(L<=l&&r<=R)
        return ans[rt];
    int mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    ll ans=0;
    if(L<mid) ans+=query(L,R,l,mid,rt<<1);
    if(R>mid) ans+=query(L,R,mid+1,r,rt<<1|1);
    return ans;
}

int main()
{

    return 0;
}

只涉及点更新的题,不需要3.5的区间更新;只涉及区间更新的不需要4的点更新
两者都有的话需要下推lazy标记

猜你喜欢

转载自blog.csdn.net/weixin_41058467/article/details/81561625