zoukankan      html  css  js  c++  java
  • poj 1733 Parity game(种类并查集)

    题意:
    有0或1构成的一段区间总长度为n。m个询问,每次询问一段区间1的个数为奇数还是偶数,问从第一个询问開始,前几个询问正确的个数有几个;
    思路:
    n<=10^9,m<=5000;非常多数用不到,所以能够离散化一下;
    将和为奇数的区间标记为1,为偶数的区间标记为0。
    对于每一个询问,合并操作时。假设两区间重合且奇偶性之和与询问所给的奇偶性同样,则该询问正确,否则错误;
    若区间不重合。合并区间,并合并奇偶性;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cmath>
    using namespace std;
    int n,m,t,cnt,ans;
    char ch[10];
    int fa[5000100],w[5000100];
    void init()
    {
        for(int i=0;i<5000100;i++)
        {
            fa[i]=i;w[i]=0;
        }
    }
    int find(int x)
    {
        if(x==fa[x]) return x;
        int temp=fa[x];
        fa[x]=find(fa[x]);
        w[x]=(w[x]+w[temp])%2;
        return fa[x];
    }
    int combine(int x,int y,int d)
    {
        int t1=find(x);
        int t2=find(y);
        if(t1==t2)
        {
            if((w[x]+w[y])%2==d) return 1; //奇偶性同样,则正确
            else return 0;
        }
        else{
            fa[t1]=t2;
            w[t1]=(w[x]+w[y]+d)%2; //更新区间奇偶性
            return 1;
        }
    }
    int main()
    {
        int i,j,k,a,b,x,y,d;
        scanf("%d%d",&n,&m);
        init();
        map<int,int>mm;
        cnt=ans=0;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%s",&a,&b,ch);a--;
            if(mm.find(a)==mm.end())
                mm[a]=cnt++;
            if(mm.find(b)==mm.end())
                mm[b]=cnt++;
            x=mm[a],y=mm[b];     //使用map实现离散化
            if(ch[0]=='o') d=1;  //奇标记
            else d=0;            //偶标记
            if(combine(x,y,d)) ans++;
            else break;
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    我所了解的meta
    移动端遇到的问题
    反编译工具
    Nginx安装及配置免费HTTPS证书
    Python中通过lambda抛异常的奇技淫巧
    理解PEP333-WSGI
    Doker学习笔记之一:安装
    《程序员修炼之道》备忘清单
    日常开发工具列表
    NLP入门资料
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7106156.html
Copyright © 2011-2022 走看看