洛谷 P5937 奇偶游戏

image

闲话

虽然这题好像找不到原题了,但毋庸置疑地说这的确是并查集的好题。

找到了 acwing

洛谷

分析

可以先对奇偶区间进行分析,当这个有偶数个 1 时,区间 \(1-(left-1)\) 一定与 区间 \(1-right\) 的奇偶性相同。

image

上面的图 \(3-4\) 为偶区间,根据分析,\(1-2\) 为奇区间。\(1-4\) 也为奇区间。

image

但如果填入的是个奇区间,那么 \(1-2\) 为奇区间,而 \(1-4\) 为偶区间。

知道这个性质我们就可以把奇数区间和偶数区间合并在一起,当遇到添加偶区间却遇到奇区间时就找到了矛盾。

我们可以用开二倍空间的数组分别存储奇区间和偶区间,其实分两个也行。

下见代码,注意这些(x-1)之类的都表示的是(1-(x-1))。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+100;//俩倍点 
int a[N];
int n,q;
int fa[N];
int find(int x){
	if(x==fa[x]){
		return x;
	}
	return fa[x]=find(fa[x]);
}

void merge(int x,int y){
	x=find(x);
	y=find(y);
	fa[y]=x;
}

int main(){
    ios::sync_with_stdio(false);
	cin>>n>>q;
	
	for(int i=0;i<=N-66;i++){
		fa[i]=i;
	}
	
	int cnt=0,ans=-1;
	
	while(++cnt){
		
		if(cnt>q){
			break;
		}
		
		int x,y;
		string s;
		cin>>x>>y>>s;
		
		if(s[0]=='e'){
			
			//奇数和偶数会合并 
			if(find(x-1)==find(y+n)&&find(x-1+n)==find(y)){
				ans=cnt;
				break;
			}
			
			merge(x-1,y);//奇数 
			merge(x-1+n,y+n);//偶数 
		}
		else{
			//奇数与奇数,偶数与偶数会合并 
			if(find(x-1)==find(y)&&find(x-1+n)==find(y+n)){
				ans=cnt;
				break;
			}
			
			merge(x-1,y+n);//偶变奇 
			merge(x-1+n,y);//奇变偶 
		}
  		
	}
	
   	cout<<ans;
   	
    return 0;
}
posted @ 2024-08-30 19:40  sad_lin  阅读(5)  评论(0编辑  收藏  举报