您的位置:首页 > 其它

vijos 1112 小胖的奇偶 并查集+哈希表

2010-07-17 11:27 856 查看
描述 Description
huyichen和xuzhenyi在玩一个游戏:他写一个由0和1组成的序列。
huyichen选其中的一段(比如第3位到第5位),问他这段里面有奇数个1
还是偶数个1。xuzhenyi回答你的问题,然后huyichen继续问。
xuzhenyi有可能在撒谎。huyichen要检查xuzhenyi的答案,指出在xuzhenyi的第几个回答一定有问题。
有问题的意思就是存在一个01序列满足这个回答前的所有回答,而且不存在序列
满足这个回答前的所有回答及这个回答。
输入格式 Input Format
第1行一个整数,是这个01序列的长度(<=1000000000)
第2行一个整数,是问题和答案的个数。
第3行开始是问题和答案,
每行先有两个整数,表示你询问的段的开始位置和结束位置。
然后是xuzhenyi的回答。odd表示有奇数个1,even表示有偶数个1。
输出格式 Output Format
输出一行,一个数X,表示存在一个01序列满足第1到第X个回答,
但是不存在序列满足第1到第X+1个回答。如果所有回答都没问题,你就输出
所有回答的个数。



样例输入 Sample Input
10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd
样例输出 Sample Output
3
来源 Source
huyichen
Flag
  Accepted
题号
  P1112
类型(?)
  并查集
通过
  592人
提交
  2720次
通过率
  22%
难度
  3
提交讨论题解状态
首先询问的个数m<=5000
如何转化成并查集?
a b even等价于(0..a-1)与(0..b)同奇同偶
a b odd等价于(0..a-1)与(0..b)不同奇同偶
这样对于a b even,就union(same(a-1),same(b))&union(diff(a-1),diff(b))
对于a b odd,则union(same(a-1),diff(b))&union(diff(a-1),same(b))
same(x)和diff(x)随便选,比如same(x):=x;diff(x):=x+block;
反之,find(same(a-1))=find(same(b))等价于a b even(此时必然有find(diff(a-1))=find(diff(b))),find(diff(a-1))=find(same(b))等价于a b odd(同样此时必然有find(same(a-1))=find(diff(b)))这样就可以判断了.
循环每个提问,先判断,不符合就writeln&break,否则union;
但这样还不可以,因为n<=10^9,会MLE.
这就用着hash了.n很大,但m很小(<=5000),这样会出现的数<=10000个,所以只需要对这10000个数DisUnionJet,为了把这10000个数一一映射到0..10000中,我们用hash.function hash(x)是原来的x在hashtable中的位置,原来的x则映射在hashtable中.以后就可以用hash(x)代替x了.这里的hash方法叫做开放寻址法(参见算法导论)
当然,这样same(x):=same(hash(x));diff(x):=diff(hash(x))
另外再设一个bb:boolean来判断如果循环后i=n时有没有经历break;
这样,程序'应该'就完成了
程序有3个难点:(1)区间奇偶转化为两区间奇偶是否相同(还是比较简单的)(2)两区间奇偶是否相同转化成并查集模型(3)利用hash压缩空间.

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int BLOCK=10000;
const int HASHING=6000;//important
int fath[2*BLOCK+1],hash_table[HASHING+1];
int hash(int x)//构建哈希表
{
int ret;
ret=x%HASHING;
while(hash_table[ret]!=-1&&hash_table[ret]!=x) ret=(ret+1)%HASHING;
hash_table[ret]=x;
return ret;
}//important
int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}
void uion(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return ;
fath[x]=y;
}
int main()
{
int len,n;
while(cin>>len>>n)
{
int ans,flag=0;
for(int i=1;i<2*BLOCK+1;i++) fath[i]=i;
memset(hash_table,-1,sizeof(hash_table));//初始化哈希表 important
for(int ci=1;ci<=n;ci++)
{
int a,b,signal;
string str;
cin>>a>>b>>str;
if(flag) continue;
signal=(str=="even"?1:0);//1表示偶数,0表示奇数
a=hash(a-1);//important
b=hash(b);//important
if(signal)
{
if(find(a)==find(b+BLOCK)) {ans=ci-1;flag=1;continue;}
uion(a,b);
uion(a+BLOCK,b+BLOCK);
}
else
{
if(find(a)==find(b)) {ans=ci-1;flag=1;continue; }
uion(a,b+BLOCK);
uion(a+BLOCK,b);
}
}
if(flag==0) ans=n;
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: