数据结构 浅谈线段树的Lazy(惰性)标记

 //未完成,明天更新...

#include <iostream>
#define MAXN 1000001
#define ll long long
using namespace std;

unsigned ll n,m,a[MAXN],ans[MAXN<<2],tag[MAXN<<2];
inline ll ls(ll x){
    return x<<1;
}
inline ll rs(ll x){
    return x<<1|1;
}
inline void scan(){
    scanf("%lld",&n); 
    for(ll i =1;i<=n;i++)
        scanf("%lld",&a[i]); 
}
inline void push_up(int k){
    ans[k] = ans[ls(k)] + ans[rs(k)];
}
void build(ll k,ll l,ll r){
    tag[k]=0;
    if(l==r){
        ans[k]=a[l];
        return;
    }
    ll mid = (l + ((r-l)>>1));
    build(ls(k),l,mid);
    build(rs(k),mid+1,r);
    push_up(k);
}

inline void f(int k,int l,int r,int c){
    tag[k] += c;//标记更新 
    ans[k] += c*(r-l+1);//更新值 
}

inline void push_down(int k,int l,int r){
    ll mid = (l+r)>>1;
    //开始从父结点传递标记给子结点 
    f(ls(k),l,mid,tag[k]);
    f(rs(k),mid+1,r,tag[k]);
    tag[k] = 0;//传递完后清空标记 
}

void update(ll k,ll tl,ll tr,ll l,ll r,ll c){//[tl,tr]目标区间,c 增加值 
    if(l>=tr&&r<=tl){
        tag[k] += c;//延迟标记让更新在下一次修改或者查询的时候发生 
        ans[k] += c*(r-l+1);
        return;
    }
    push_down(k,l,r);
    ll mid = (l+r)<<1;
    if(l<=mid)
        update(ls(k),tl,tr,l,mid,c);
    if(r>mid)
        update(rs(k),tl,tr,mid+1,r,c);
    push_up(k);
}

ll query(ll k,ll tl,ll tr,ll l,ll r){
    ll res = 0;
    if(l>=tl&&r<=tr){
        return ans[k];
    }
    ll mid = (l+r)<<1;
    push_down(k,l,r);
    if(l<=mid)
        res += query(ls(k),tl,tr,l,mid);
    if(r>mid)
        res += query(rs(k),tl,tr,mid+1,r);
    return res;
}

int main(){
    scan();
    build(1,1,n);
    
    return 0;
}

参考资料:

洛谷日报#4

猜你喜欢

转载自www.cnblogs.com/--zz/p/10720397.html