[POJ1733] [CEOI1999] Parity Game [带权并查集]

题意:给出一个长为 N N 的01序列。猜测 M M 段子区间 [ A i , B i ] [A_i,B_i] 的奇偶性
求存在01序列满足前 x x 个猜测的最大 x x
( N 1 0 9 , M 5 1 0 3 ) (N\le 10^9,M\le 5*10^3)

不知道带权并查集的时候我想了半天没想出来线段树怎么搞(

类似这种逐个输入判断是否和之前给出的判断相悖的题目都是带权并查集

如果题目不是要求满足前 x x 个猜测而是满足 x x 个猜测那就不一样了

首先 N N 太大了需要一波离散化

奇偶性很好搞,反正就是异或啦。想要 % 2 \%2 也随意

不要忘了左开右闭或者左闭右开

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
using namespace std;
int N,M,fx,fy,x,y;
int sx[5005]={},sy[5005]={};
bool p[5005]={};
int t[10005]={},tot=0;
int fa[10005]={},val[10005]={};
char ch;
int find(int x)
{
	if(fa[x]==x)return x;
	else
	{
		int t=find(fa[x]);
		val[x]^=val[fa[x]];
		return fa[x]=t;
	}
}
int main()
{
	scanf("%d%d",&N,&M);
	for(int i=1;i<=M;++i)
	{
		scanf("%d%d",&sx[i],&sy[i]); --sx[i]; t[++tot]=sx[i]; t[++tot]=sy[i];
		while(!isalpha(ch))ch=getchar();
		p[i]=(ch=='o');
		while(isalpha(ch))ch=getchar();
	}
	sort(t+1,t+1+tot); tot=unique(t+1,t+1+tot)-t-1;
	for(int i=0;i<=tot;++i)fa[i]=i;
	for(int i=1;i<=M;++i)
	{
		x=lower_bound(t+1,t+1+tot,sx[i])-t;
		y=lower_bound(t+1,t+1+tot,sy[i])-t;
		fx=find(x),fy=find(y);
		if(fx!=fy)
		{
			fa[fy]=fx;
			val[fy]=val[y]^val[x]^p[i];
		}
		else if((val[x]^val[y])!=p[i])
		{
			printf("%d",i-1);
			return 0;
		}
	}
	printf("%d",M);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/82873646