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);
    }
    
  • 相关阅读:
    套用JQuery EasyUI列表显示数据、分页、查询
    Linux 进程间通信 信号
    Linux socket编程
    Linux字符设备驱动注册流程
    Linux杂项设备与字符设备
    Linux并发控制解决竞态的一种操作>原子操作
    Linux 进程间通信 管道通信
    Linux串口编程
    博客开通啦!
    实现Windows Phone 8多媒体:视频
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7106156.html
Copyright © 2011-2022 走看看