poj 1733 Parity game(种类并查集)

来源:互联网 发布:linux 搭建OpenVPN 编辑:程序博客网 时间:2024/04/28 20:55

题意:
有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);}
1 0
原创粉丝点击