首页 > 代码库 > 小胖的奇遇——论玄学

小胖的奇遇——论玄学

小胖的奇偶

题目描述:

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绝望了。)

小胖的奇遇——论玄学