您的位置:首页 > 其它

poj 1733 Parity game(种类并查集)

2015-07-28 11:55 441 查看
题意:

有0或1构成的一段区间总长度为n,m个询问,每次询问一段区间1的个数为奇数还是偶数,问从第一个询问开始,前几个询问正确的个数有几个;

思路:

n<=10^9,m<=5000;很多数用不到,所以可以离散化一下;

将和为奇数的区间标记为1,为偶数的区间标记为0;

对于每个询问,合并操作时,如果两区间重合且奇偶性之和与询问所给的奇偶性相同,则该询问正确,否则错误;

若区间不重合,合并区间,并合并奇偶性;

[code]#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: