加载中...

ABC 441 G(线段树多懒标记维护)

G - Takoyaki and Flip

一道有助于理解线段树懒标记下传的好题,其中也涉及到了带有优先级的懒标记的先后处理方式。内容见 code 部分。

参考:zhihu

这位博主将 对懒标记的处理 又单独开了一个函数 \(settag\),使 线段树结点值的修改懒标记的合并 的过程结构化,\(pushup\)\(pushdown\) 看着更加清晰,感觉值得去学习一下。

code

顺便贴一个自己写的 同时维护 区间加 + 区间赋值 操作,并维护区间最大值的线段树,以后遇到类似题了再检验下写得对不对。

// max
template<typename T>
struct SegTree
{
    struct Node
    {
        int l, r;
        T maxv, tag_fix, tag_add;
    }tr[maxn << 2];

    #define lc p<<1
    #define rc p<<1|1

    void pushup(int p)
    {
		tr[p].maxv = max(tr[lc].maxv, tr[rc].maxv);
    }

    void pushdown(int p)
    {
        if(tr[p].tag_fix != -1){
            tr[lc].maxv = tr[rc].maxv = tr[p].tag_fix; 
        }
        if(tr[p].tag_add){
            tr[lc].maxv += tr[p].tag_add;
            tr[rc].maxv += tr[p].tag_add;
        }


        if(tr[p].tag_fix != -1){
            tr[lc].tag_fix = tr[rc].tag_fix = tr[p].tag_fix;
            tr[lc].tag_add = tr[rc].tag_add = 0;
        }
        if(tr[p].tag_add){
            tr[lc].tag_add += tr[p].tag_add;
            tr[rc].tag_add += tr[p].tag_add;
        }

        tr[p].tag_fix = -1;
        tr[p].tag_add = 0;
    }

    void build(int p, int l, int r,auto& arr)
    {
        tr[p] = { l,r,arr[l],-1,0};
        if (l == r) return;
        int mid = l + r >> 1;
        build(lc, l, mid , arr);
        build(rc, mid + 1, r , arr);
        pushup(p);
    }

    void update_fix(int p, int l, int r, T k)
    {
        if (l <= tr[p].l && tr[p].r <= r) 
        {
			tr[p].maxv = k;
            tr[p].tag_fix = k;
            tr[p].tag_add = 0;
            return;
        }
        int mid = tr[p].l + tr[p].r >> 1;
        pushdown(p);
        if (l <= mid) update_fix(lc, l ,r, k);
        if (r > mid)  update_fix(rc, l ,r, k);
        pushup(p);
    }

    void update_add(int p, int l, int r, T k)
    {
        if (l <= tr[p].l && tr[p].r <= r)
        {
			tr[p].maxv += k;
            tr[p].tag_add += k;
            return;
        }
        int mid = tr[p].l + tr[p].r >> 1;
        pushdown(p);
        if (l <= mid) update_add(lc, l ,r, k);
        if (r > mid)  update_add(rc, l ,r, k);
        pushup(p);
    }

    T querymax(int p, int l, int r)
    {
        if (l <= tr[p].l && tr[p].r <= r) return tr[p].maxv;
        pushdown(p);
        int mid = tr[p].l + tr[p].r >> 1;
        T maxv = INT_MIN;
        if (l <= mid) maxv = max(maxv, querymax(lc, l, r));
        if (r > mid) maxv = max(maxv, querymax(rc, l, r));
        return maxv;
    }

};
posted @ 2026-01-18 16:58  jxs123  阅读(3)  评论(0)    收藏  举报