线段树专题

李超线段树

解决一类区间等差数列(线段)求最值的问题。
做法为用线段树来维护,为了使复杂度正确,我们采用标记永久化,并且通过分类讨论,将每次标记下传的大小减半,达到\(O(nlogn)\)的复杂度。
[JSOI2008]Blue Mary开公司 代码
[HEOI2013]Segment
[SDOI2016]游戏


线段树分治

解决一类在时间轴上一段时间里操作有贡献,询问某一时刻的贡献和。
考虑离线的做法,在时间轴上建立线段树。每个节点维护对此区间的贡献,然后最终遍历整个线段树,用一定的数据结构来维护贡献。具体实现的时候,将一个操作看作是对一个区间的修改,将操作存在线段树上节点的vector中,回答询问的时候,只要整体做一次dfs。
二分图
[AHOI2013]连通图


线段树合并、分裂

int merge(int p,int q,int l,int r){
    if(!p)return q;if(!q)return p;
    if(l==r){t[p].val+=t[q].val;return p;}
    int mid=(l+r)>>1;t[p].ls=merge(t[p].ls,t[q].ls,l,mid);t[p].rs=merge(t[p].rs,t[q].rs,mid+1,r);
    t[p].val=std::max(t[t[p].ls].val,t[t[p].rs].val);
}

void split(int &p,int q,int k){//权值线段树上分裂出前k小的数,p为后k小
    int val=t[t[q].ls].val;
    if(k>val)split(t[p].rs,t[q].rs,k-val);
    else{
        swap(t[p].rs,t[q].rs);
        if(k<val)split(t[p].ls,t[q].rs,k);
    }
    t[p].val=t[q].val-k;t[q].val=k;return;
}

线段树上二分

posted @ 2020-10-25 11:17  行zzz  阅读(102)  评论(0编辑  收藏  举报