POJ 1733 Parity game

本文介绍了一种使用哈希离散化和并查集解决区间问题的方法。通过离散化处理,将区间内的1的个数奇偶性进行计算和判断,利用并查集实现区间合并,优化查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解题思路:hash离散化+并查集

首先我们不考虑离散化:s[x]表示(root[x],x]区间1的个数的奇偶性,0-偶数,1-奇数

每个输入区间[a,b],首先判断a-1与b的根节点是否相同

a)如果相同表示(a-1,b]之间1的个数奇偶性已知s((a-1,b])=s[a-1]^s[b],此时只需简单判断即可

b)如果不同,我们需要合并两个子树,我们将root较大的子树(例root[a])合并到root较小的子树(例root[b]),且此时s[root[a]]=s[a]^s[b]^s((a-1,b])

在路径压缩的过程中s[i]=s[i]^s[root[i]],s[root[i]]为(root[root[i]], root[i]]区间内1个数的奇偶性,例(a, b]区间1的个数为偶数,(b, c]区间1的个数为奇数,(a, c]之间1的个数显然为0^1=1奇数

欢迎review
#include <iostream>
using namespace std;
#define MOD 9941
#define MAX 10005

struct node
{
node():next(
0){}
int val, index;
node
* next;
}HashMap[MOD];

int root[MAX],num[MAX],u=0;
char c[MAX];
int find(int x)
{
int y = x%MOD;
node
*p,*q;
p
= &HashMap[y], q = HashMap[y].next;
while (q)
if(q->val == x)return q->index;
else p=q,q=q->next;
node
*temp=new node(); temp->val=x,temp->index=++u,p->next=temp,num[u]=x;
return u;
}
int findroot(int x)
{
int t;
if(root[x]!=x){t = root[x];root[x]=findroot(root[x]);c[x] = c[t]^c[x];}
return root[x];
}
int main()
{
int i,l,n,s,t,r1,r2,v,ans;
bool IsError = false;
char ch[5];
for(i=0;i<MAX;i++)root[i]=i,c[i]=0;
scanf(
"%d\n%d", &l, &n);
for (i=1; i<=n;i++)
{
scanf(
"%d %d %s", &s, &t, ch);
if(IsError)continue;
v
= (ch[0] == 'e')?0:1;
s
=find(s-1),t=find(t);
r1
=findroot(s), r2=findroot(t);
if(r1==r2 && (c[s]^c[t]^v)){IsError=true;ans=i-1;}
else if(r1 != r2)
{
if(num[r1]<num[r2])root[r2]=r1,c[r2]=c[s]^c[t]^v;
else root[r1]=r2, c[r1]=c[s]^c[t]^v;
}
}
IsError
? printf("%d\n",ans) : printf("%d\n", n);
return 0;
}

 

转载于:https://www.cnblogs.com/ltang/archive/2010/12/07/1898919.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值