首页 > 代码库 > poj 1733 Parity game(种类并查集)

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\n",ans);
}
<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

poj 1733 Parity game(种类并查集)