奇偶游戏

奇偶游戏

题意:

小 A和小 B 在玩一个游戏。

首先,小 A写了一个由 0 和 1组成的序列 S,长度为 N。

然后,小 B 向小 A 提出了 M 个问题。

在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r]中有奇数个 1还是偶数个 1。

机智的小 B 发现小 A 有可能在撒谎。

例如,小 A 曾经回答过 S[1∼3] 中有奇数个 1,S[4∼6] 中有偶数个 1,现在又回答 S[1∼6]中有偶数个 1,显然这是自相矛盾的。

请你帮助小 B 检查这 M个答案,并指出在至少多少个回答之后可以确定小 A一定在撒谎。

即求出一个最小的 kk,使得 01 序列 S 满足第 1∼k 个回答,但不满足第 1∼k+1个回答。

思路:

前缀和+异或性质+并查集+离散化
我们可以用d数组表示序列S的前缀和,那么会得到以下性质.
d[l~r]有偶数个1,等价于d[l-1]与d[r]奇偶性相同 (1+0=1 0+0=0,1是奇数,0是偶数)
d[l~r]有奇数个1,等价于d[l-1]与d[r]奇偶性不同 (1+1=0 0+1=0,1是奇数,0是偶数

以下是传递关系细目表
如果说x1和x2奇偶性质相同,x2与x3奇偶性质相同,那么x1和x3也相同
如果说x1和x2奇偶性质相同,x2与x3奇偶性质不同,那么x1和x3也不同
如果说x1和x2奇偶性质不同,x2与x3奇偶性质不同,那么x1和x3就相同

代码:

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e4+10;
int f[N],d[N],cnt;	
int n;
unordered_map<int,int>mp;
int find(int x){
	if(x!=f[x]){
		int root=find(f[x]);
		d[x]^=d[f[x]];
		x=root;
	}
	return f[x];
}
int get(int x){//离散化 
	if(mp.count(x)==0){
		mp[x]=++cnt;
	}
	return mp[x];
}
signed main(){
	cin>>n;
	int m;
	cin>>m;
	int flag=1;
	for(int i=1;i<N;i++){
		f[i]=i;
	} 
	for(int i=1;i<=m;i++){
		string s;
		int l,r;
		cin>>l>>r>>s;
		if(flag==0) continue;
		l--;
		l=get(l);
		r=get(r); 
		int cha=0;
		if(s=="odd"){
			cha=1;
		}
		int fa=find(l);
		int fb=find(r);
		if(fa!=fb){
			f[fa]=fb;
			d[fa]=d[l]^d[r]^cha;
		}
		else{
			if(d[l]^d[r]!=cha){
				cout<<i-1<<endl;
				flag=0;
			}
		}
	}
	if(flag) cout<<m<<endl;
} 

posted @ 2021-09-05 21:41  Curry_BP  阅读(112)  评论(0)    收藏  举报