首页 > 其他分享 >CF-292-D-并查集

CF-292-D-并查集

时间:2024-01-23 10:45:23浏览次数:36  
标签:pre suf DSU int siz 查集 CF 292

292-D 题目大意

给定一张无向图,由\(n\)个顶点\(m\)条边。有\(q\)次询问,每次询问将\([l,r]\)的边删去,问图中有多少连通分量。


Solution

涉及连通分量,尝试应用并查集解决。

记录一个前缀并查集\(pre[i]\),表示前\(i\)条边连通后的图;和一个后缀并查集\(suf[i]\),表示后\(m-i\)条边连通后的图。

对于一个询问\([l,r]\),把\(pre[l-1]\)和\(suf[r+1]\)两个并查集拼起来,再统计连通分量即可。

时间复杂度\(O((m+qn)α(n))\)。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;

template<typename T>
struct DSU{
	int n;
	vector<T> p,siz;
	DSU(int _n):p(_n+1),siz(_n+1),n(_n){
		iota(p.begin(),p.end(),0);
		for(int i=0;i<=n;i++) siz[i]=1;
	}
	T findd(T x){
		return p[x]==x?x:p[x]=findd(p[x]);
	}
	void unionn(T x,T y){
		x=findd(x),y=findd(y);
		if(x==y) return;
		if(siz[x]>siz[y]) swap(x,y);
		p[x]=y;
		siz[y]+=siz[x];
	}
};

void solve(){
    int n,m;
    cin>>n>>m;
    vector<DSU<int>> pre(m+2,DSU<int>(n)),suf(m+2,DSU<int>(n));
    vector<pair<int,int>> e(m);
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        e[i]={x,y};
    }
    for(int i=1;i<=m;i++){
        auto [x,y]=e[i-1];
        pre[i]=pre[i-1];
        pre[i].unionn(x,y);
    }
    for(int i=m;i;i--){
        auto [x,y]=e[i-1];
        suf[i]=suf[i+1];
        suf[i].unionn(x,y);
    }
    int q;
    cin>>q;
    while(q--){
        int l,r;
        cin>>l>>r;
        auto u=pre[l-1],v=suf[r+1];
        for(int i=1;i<=n;i++){
            u.unionn(i,v.findd(i));
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(u.p[i]==i){
                ans++;
            }
        }
        cout<<ans<<'\n';
    }
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

标签:pre,suf,DSU,int,siz,查集,CF,292
From: https://www.cnblogs.com/fengxue-K/p/17981825

相关文章

  • CF1424M Ancient Language 题解
    1.题意描述一本字典中有\(r\)\((1\leqr\leq10^6)\)个单词,单词长度不超过$10^3$,所有字母都是小写英文字母,但字母排序不是按英文字母排序,求所有出现字母的一种排序,如果不存在,输出"IMPOSSIBLE"。2.题目分析由排序规则可知,对于字符串\(s\)和\(t\),\(s\)排在\(t\)......
  • CF618C Constellation 题解
    题意描述给定\(n\)个点(\(n\leq10^5\)),找到三个点满足这三个点不在同一直线上且三个点构成的三角形中不包含其他点,保证所有点不会在同一直线上。题目分析首先必然每一个点都可以作为一组解中的点。不妨其中一个点编号为\(1\)。找一个点作为第二个点,为了使没有点在这条边上,这......
  • CF1036F Relatively Prime Powers 题解
    题目分析对于一个不合法的数\(x(x\ge2)\),设\(x=\prodp_i^{r_i}\),令\(g=\gcd(r_1,r_2,\ldots,r_k)\),则\(x=\left(\prodp_i^{r_i/g}\right)^g\),所以\(x\)是一个正整数的\(g\)次方。所以可以枚举上文的\(g\),把每一类不合法方案排除掉,就是答案。设\(f(i)\)表示\(2\)......
  • CF1914D Three Activities
    题目大意给定三个数组\(a,b,c\)找三个互不相同的整数\(i,j,k\)使得\(a_i+b_j+c_k\)的值最大.思路首先想到的当然是枚举\(i,j,k\)然后找到最大值,但这种方法的时间复杂度是\(O(n^3)\),显然会喜提\(TLE\).当然由瞪眼法可知,因为我们只需要找到\(a_i+b_j......
  • CF-1831-E-卡特兰数+异或哈希+差分
    1831-E题目大意给定一个整数\(n\),和\(k\)个区间,区间端点范围在\([1,n]\)内。如果有一个长为\(n\)合法的括号序列,且它的这\(k\)个区间\([l,r]\)中的子括号序列也是合法的,那么称这个括号序列是“好的”。请你求出有多少个长度为\(n\)的“好的”括号序列,答案对\(998244353\)取模......
  • 从CF1875C学习lowbit运算判断是否为 2 的 k 次幂
    Problem-1875C-Codeforces本题判断无解的时候要判断该数是否为2的k次幂,我的做法是预处理出2的次幂数表。看题解发现可以用lowbit操作。lowbit操作intlowbit(intx){returnx&(-x);}根据补码原理,该操作可以求出来X最靠右的\(1\)构成的数。判断\(x\)......
  • 从CF1878E学习前缀和维护二进制拆位分析思想
    Problem-1878E-Codeforces这题我想到了个大概,按位与的话结果肯定是递减的,而且要从二进制每一位下手,但是思路只停留在暴力对整个数操作。当然,利用这个性质,肯定要二分。拆位思想比如要计算111000111011100100010我们知道最后结果肯定是留下都有\(1\)的位0100000......
  • CF1922F Replace on Segment
    看到有区间操作,结合\(n\le100\)的数据范围,直接考虑区间dp。设\(f_{l,r,x}\)表示将区间\([l,r]\)全部替换成\(x\)的最小步数。首先有\(f_{l,r,x}=\max_{p=l}^{r-1}f_{l,p,x}+f_{p+1,r,x}\),但这无法将该状态下的所有的情况都转移到,所以考虑再设一个\(g_{l,r,x}\)表示......
  • CF1770C
    分析不难发现,由于\(x>0\),所以当出现两个相同数的时候一定是NO。再然后,发现对于一个数\(k\),记\(re_i\)表示\(a\)中模\(k\)余\(i\)的数的个数,若对于所有的\(0\lei<k\),都有\(re_i>1\),那么不管你加多少,必定有至少\(2\)个\(k\)的倍数,不互质,因此也是NO。剩下的就是......
  • CF-1399-E2-优先队列
    1399-E2题目大意给定一棵\(n\)个节点的树,边带权,根节点为\(1\)。再给定一个整数\(S\),你可以执行以下操作:选择一条权值为\(w_i\)的边,令\(w_i\rightarrow\lfloor\frac{w_i}{2}\rfloor\)。你可以执行任意次操作,使得\(\sum_{x∈leaves}sum(1,x)\)不大于\(S\),其中\(sum(1,x)\)......