• luogu集合刷题进阶


    昨天光顾着聊天忘记存盘了,写到一半的blog就,,,没了

    今天主要是绿题怕怕,

    主要是两个集合之间的东西,,,比如并查集

    P1982

    反集:

    如果a和b是敌人,合并n+b和a,n+a和b

    如果c和a是敌人,合并n+c和a,n+a和c

    那么b和c就并在一起了

    这样就符合了题目敌人的敌人是朋友的规则

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    #include<bits/stdc++.h>
    using namespace std;
    int s,n,m,a,b,f[2500];
    char ch;
    int find(int x){
        if(f[x]!=x)f[x]=find(f[x]);
        return f[x];
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=2*n;i++){
            f[i]=i;//初始化,千万不能漏
        }
        for(int i=1;i<=m;i++){
            cin>>ch>>a>>b;
            if(ch=='F'){
                f[find(a)]=find(b);//合并
            }else{
                f[find(a+n)]=find(b);
                f[find(b+n)]=find(a);//反集合并
            }
        }
        for(int i=1;i<=n;i++){
            if(f[i]==i)
                s++;
        }
        cout<<s;//祖先数就是团伙数
    }
    

    感谢大佬https://www.luogu.com.cn/blog/81591/solution-p1892

    p1621

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #define maxn 100010
    using namespace std;
    int f[maxn];
    int a,b,p,ans;
    bool prime[maxn];
    int vis[maxn];
    int cnt;
    int getf(int x)
    {
        if(f[x]==x) return x;
        else
        {
            f[x]=getf(f[x]);
            return f[x];
        }
    }
    int merge(int x,int y)
    {
        int t1=getf(x),t2=getf(y);
        if(t1!=t2)
        {
            f[t2]=t1;
            return 1;
        }
        return 0;
    }
    int make_prime()      //普通筛
    {
        memset(prime,1,sizeof(prime));
        int k=sqrt(b);
        prime[0]=prime[1]=0;
        for(int i=2;i<=k;i++)
            if(prime[i])
                for(int j=2*i;j<maxn;j+=i) prime[j]=0;
    }
    int main()
    {
        cin>>a>>b>>p;
        for(int i=a;i<=b;i++)
            f[i]=i;
        make_prime();
        //把大于p的质数标记一下
        for(int i=p;i<=b;i++)
            if(prime[i]) vis[++cnt]=i;
            
          //开始用标记的数乘一个倍数  
        for(int i=1;i<=cnt;i++)
        {
            int cc=0;
            while(cc*vis[i]<a) cc++;
            while(vis[i]*(cc+1)<=b)
            {
                merge(vis[i]*cc,vis[i]*(cc+1));     //合并
                cc++;
            }
        }
        for(int i=a;i<=b;i++)
            if(f[i]==i) ans++;     //统计个数
        cout<<ans<<endl;
        return 0;
    }
    
    为了自己,和那些爱你的人
  • 相关阅读:
    win7,win10获取屏幕缩放适应截图
    cg语言学习&&阳春白雪GPU编程入门学习
    Unity Plugins的使用方法
    记录Unity的优化tip(不断更新)
    深入理解法线贴图原理
    读香菱学诗
    排序算法学习
    图的算法复习大纲
    Gama Space 和 Linear Space 学习
    BM算法学习
  • 原文地址:https://www.cnblogs.com/zhmlzhml/p/14394950.html
Copyright © 2020-2023  润新知