POJ1733:Parity game

浅谈并查集:https://www.cnblogs.com/AKMer/p/10360090.html

题目传送门:http://poj.org/problem?id=1733

带权并查集裸题。区间和可以由前缀和相减得到,如果区间\([l,r]\)为奇数,那么\(sum[l-1]\)\(sum[r]\)奇偶性就不同,否则反之。

用并查集合并\(l-1\)\(r\)的同时维护一个\(d\)数组,\(d[x]\)表示\(x\)与祖先的奇偶性是否相同,可以直接异或求得。

时间复杂度:\(O(\alpha{m})\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=1e4+5;

char s[5];
int n,m,cnt;
int l[maxn],r[maxn],opt[maxn];
int fa[maxn],d[maxn],tmp[maxn<<1];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

int find(int x) {
	if(fa[x]==x)return x;
	int tmp=fa[x];
	fa[x]=find(fa[x]);
	d[x]^=d[tmp];return fa[x];
}

int main() {
	n=read(),m=read();
	for(int i=1;i<=m;i++) {
		tmp[i]=l[i]=read()-1;
		tmp[i+m]=r[i]=read();
		scanf("%s",s+1);
		if(s[1]=='e')opt[i]=0;
		else opt[i]=1;
	}
	sort(tmp+1,tmp+(m<<1)+1);
	cnt=unique(tmp+1,tmp+(m<<1)+1)-tmp-1;
	for(int i=1;i<=m;i++) {
		l[i]=lower_bound(tmp+1,tmp+cnt+1,l[i])-tmp;
		r[i]=lower_bound(tmp+1,tmp+cnt+1,r[i])-tmp;
	}
	for(int i=1;i<=cnt;i++)fa[i]=i;
	for(int i=1;i<=m;i++) {
		int p=find(l[i]),q=find(r[i]);
		if(p==q&&(d[l[i]]^d[r[i]])!=opt[i]) {
			printf("%d\n",i-1);return 0;
		}
		else if(p!=q)fa[p]=q,d[p]=opt[i]^d[l[i]]^d[r[i]];
	}
	printf("%d\n",m);
	return 0;
}
posted @ 2019-02-13 11:22  AKMer  阅读(94)  评论(0编辑  收藏  举报