【题解】CF603E | 半在线线段树分治

题意翻译的很清楚,不再叙述。

有一个结论就是 “偶数度连通块是有解的充分必要条件” ,很多题解说的都是“调整法”,便于理解,但给出一个具体化的证明,如下:

答案是生森林是显然的,因为环一定可以从集合中删去使得答案更优

首先,奇数大小的连通块的边数为偶数,每条边对总度数的贡献是 2,而总度数等于 奇数 * 奇数 仍然为奇数,故是必要条件。

对于充分性,只要给出一组构造即可。

令 $S(x)$ 表示大小为 2x 的连通块。

对于大小为 0 的连通块 $S(0)$ 空集为解。

对于大小为 2 的连通块 $S(1)$ 有解,直接选择二点之间的边即有解。

对于 $S(x)$ 若 $S(p) (p\in \mathbb{N},p < x)$ 有解,则 $S(x)$ 有解。

,证明如下:

因为该连通块的大小是偶数,所以该连通块一定可以被划分成两个大小为偶数的连通块,或两个大小为奇数的连通块。

若该连通块可以被约化为 $S(x-p) , S(p) (0 < p < x)$ 两边都有解。

若该连通块不能被划分成两个偶数大小的连通块,则任意选择一条边,将这条边加入边集,钦定这两个点不再被其他边连接,可以约化成 $S(x - 1 - p) , S(p) (0\leq p \leq x - 1) $ 。

故 $S(x)$ 若 $S(p) (p\in \mathbb{N},p < x)$ 有解,则 $S(x)$ 有解。

由数学归纳法, $S(0)$ 有解,又因上定理,故偶数大小是成立的充分必要条件。

回到本题,已经解决静态问题了,考虑“加边”怎么处理。

将“加边”离线,然后由于答案是单调不降的,选的边只会越来越大,考虑倒着计算,将边按权值排序,先按顺序加入边直道答案成立(用一个指针从左向右加—),知道该边的起始时间的前一个时刻把这条边删了,继续加入边即可。

但是由于“删边”很难实现,又因为和图的连通性有关,于是考虑用一个半在线的线段树分治去维护它,记录奇数大小的连通块数,使用可撤销并查集,先遍历右儿子,遍历到叶节点就判断,并向前面区间加边即可。

一个坑点是不能在 $[tim , l]$ 直接连边( $tim$ 表示这条边的出现时间, $l$ 表示目前分治到的时间点) 因为已经遍历到了这个叶子,可能导致上面的标记没有生效,应在 $[tim , l - 1]$ 连边。

线段树分治部分代码:

/*uniset 表示合并 , disset表示拆分 ,O记录操作以撤回 , cnt表示目前奇数大小的连通块数*/
/*本人码风、缩进略怪,多多包涵*/
void solve(int x,int l,int r) {
    vector<Pair> O;
    for(int p : ed[x]) {
        int U = find(e[p].u) , V = find(e[p].v) ;
        if(U^V) {
            if(siz[U] < siz[V]) swap(U,V) ; 
            uniset(U,V); O.emplace_back(U,V);
        }
    }
    if(l == r) {
            while (cnt && ptr <= m) {
                if(e[ptr].tim <= l)
                {
                    int U = find(e[ptr].u) , V = find(e[ptr].v) ;
                    if(U^V) {
                        if(siz[U] < siz[V]) swap(U,V) ; 
                        uniset(U,V); O.emplace_back(U,V);
                    }
                    adde(1,1,m,e[ptr].tim,l - 1,ptr); /*坑点就是这里!!!*/
                }
            ptr ++ ;  
        }
        if(!cnt) ans[l] = e[ptr - 1].w; else ans[l] = -1 ;
    }
    else {
        int mid = l + r >> 1;
        solve(x<<1|1,mid+1,r);
        solve(x<<1,l,mid) ;
    }
    reverse(All(O)) ;
    for(auto[U,V]:O) disset(U,V) ;
}

ACcode

(有快读之类的东西,define极多,观感不佳,上方代码为方便阅读进行了缩进修改,删除了部分注释。)

如有笔误、逻辑错误欢迎轻喷。

感谢您的阅读,感谢管理员辛苦审核。

posted @ 2022-05-24 23:00  寂静的海底  阅读(11)  评论(0编辑  收藏  举报  来源