小胖的奇偶
题目描述:
huyichen和xuzhenyi在玩一个游戏:他写一个由0和1组成的序列。
huyichen选其中的一段(比如第3位到第5位),问他这段里面有奇数个1还是偶数个1。
xuzhenyi回答你的问题,然后huyichen继续问。
xuzhenyi有可能在撒谎。huyichen要检查xuzhenyi的答案,指出在xuzhenyi的第几个回答一定有问题。
有问题的意思就是存在一个01序列满足这个回答前的所有回答,而且不存在序列满足包括这个回答在内的所有回答,也就是自相矛盾。
输入格式:
第1行一个整数,是这个01序列的长度(<=1000000000)
第2行一个整数,是问题和答案的个数。
第3行开始是问题和答案,
每行先有两个整数,表示你询问的段的开始位置和结束位置。
然后是xuzhenyi的回答。odd表示有奇数个1,even表示有偶数个1。
输出格式:
输出一行,一个数X,表示存在一个01序列满足第1到第X个回答,
但是不存在序列满足第1到第X+1个回答。如果所有回答都没问题,你就输出
所有回答的个数。
样例输入:
10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd
样例输出:
3
时间限制:1000ms
空间限制:128MByte
这个题目简单来说就是一个并查集的题目,当在x到y区间有even个1时,我们可以得出在0到x-1和0到y区间中的1的个数的奇偶性是相同的,同理若有odd个1,0到x-1和0到y区间的1的个数的奇偶性就是不同的;所以我们就可以将数组分为两个部分表示是否相同与是否不同,我们可以用一个比较大的mod保证两个区间不重合,但是一看,(这个01序列的长度(<=1000000000))就知道我们不能naive地AC,因为这个数组太大了根本开不下,但是我们可以猜出这个询问并不会这么多(玄学*1);所以这个时候我们就需要用到STL!之前看的题解的话大多都是用哈希表,但是根据玄学,我们猜出询问次数不会很多,所以,可以用map来解决这个神奇的问题。(顺便还向大佬请教了一下map的用法)
#include<bits/stdc++.h> #define mod 1000000000 using namespace std; map<int,int> f; int n,m,pos; string s; void st(int x){ if (f.count(x)==0) f[x]=x; }//这个函数用于判断次节点是否有初值,若没有则将它自己的父亲设定为自己; int find(int x){ if (x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } bool same(int x,int y){ return find(x)==find(y); } void link(int x,int y){ f[find(x)]=find(y); } int main(){ cin>>n>>m; pos=-1; for (int k=1; k<=m; k++){ int x,y; cin>>x>>y>>s; if (pos!=-1) break; st(x-1);st(y);st(x-1+mod);st(y+mod); if (s[0]==‘e‘){ if (same(x-1,y+mod) || same(x-1+mod,y)){ pos=k; } link(x-1,y); link(x-1+mod,y+mod); } else { if (same(x-1,y) || same(x-1+mod,y+mod)){ pos=k; } link(x-1,y+mod); link(x-1+mod,y); } } if (pos!=-1) cout<<pos-1<<endl; else cout<<m<<endl; return 0; }
啊哈哈,你以为这样就AC了吗?naive!但是是不是觉得之前的推理很有道理?对啊!我也是怎么觉得的,但是这惨痛的分数告诉了我们这个冷酷的事实.
没错,我也很想不通,改了又改,改了又改。最终,还是去求助大佬了。听了大佬的思路。woc,这和我的思路不是一样的吗?(玄学*2),唯一不同的一点就是,他的区间分别是0~x和0~y+1,而我的思路是0~x-1和0~y(玄学*3),于是我带着试一试的思路试了一试(玄学*4)。
#include<bits/stdc++.h> #define mod 1000000006 using namespace std; map<int,int> f; int n,m,pos; string s; void st(int x){ if (f.count(x)==0) f[x]=x; } int find(int x){ if (x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } bool same(int x,int y){ return find(x)==find(y); } void link(int x,int y){ f[find(x)]=find(y); } int main(){ cin>>n>>m; pos=-1; for (int k=1; k<=m; k++){ int x,y; cin>>x>>y>>s; if (pos!=-1) break; st(x);st(y+1);st(x+mod);st(y+1+mod); if (s[0]==‘e‘){ if (same(x,y+1+mod) || same(x+mod,y+1)){ pos=k; } link(x,y+1); link(x+mod,y+1+mod); } else { if (same(x+mod,y+1+mod) || same(x,y+1)){ pos=k; } link(x,y+1+mod); link(x+mod,y+1); } } if (pos!=-1) cout<<pos-1<<endl; else cout<<m<<endl; return 0; }
呵呵呵呵,玄学玄学,社会社会,(玄学*5),嗯哼?我会说我很绝望吗?当然不会了。(woc明天居然还有考试我当然绝望了!太tm绝望了。)