线段树 与 树状数组进阶

通过观察 rqy 的题解,发现可以考虑只有区间推平操作的历史和问题。

现有问题:给定一个序列,操作要求区间推平,维护历史版本和。

考虑在线段树上维护 \(s,hs,l\) 表示区间和、区间历史版本和、区间长度。
\((tg,htg,upd)\) 表示标记队列。

考虑一个线段树节点加上一个标记队列:
先考虑标记队列是否有标记。如果有标记,就推平,考虑原来的节点信息是否有标记,如果有标记,就把新来 \(upd\) 转移到 \(htg\) 里面,否则继续下传 \(upd\) 标记。如果标记队列没有标记,那么直接加上区间和即可

struct node{
    LL hs,s,tg,htg,upd; int l;
    void addt(LL tg2,LL htg2,LL upd2){
        if(tg2){
            hs+=upd2*s+htg2*l; htg+=htg2; s=tg2*l;
            if(tg) htg+=upd2*tg;
            else upd+=upd2;
            tg=tg2;
        }
        else {
            hs+=upd2*s;
            if(tg) htg+=upd2*tg;
            else upd+=upd2;
        }
    }
} 

说不定可以即支持区间推平和区间加,即考虑在加法标记队列后面维护一个推平标记队列,如果有加法加进来就考虑变成标记队列。

posted @ 2023-08-20 22:41  Shui_dream  阅读(72)  评论(1)    收藏  举报