51nod 1204:Parity 并查集

题目来源:  Ural
基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注
你的朋友写下一串包含1和0的串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以继续提问......你怀疑朋友的答案可能有错,或说同他之前的答案相互矛盾,例如:1 - 2 奇数,3 - 4 奇数,那么可以确定1 - 4 一定是偶数,如果你的朋友回答是奇数,就产生了矛盾。给出所有你朋友的答案,请你找出第一个出现矛盾的答案。
Input
第1行:2个数N, Q,N为串的长度,Q为询问的数量。(2 <= N <= 100000, 2 <= Q <= 50000)
第2 - Q + 1行:每行包括两个数以及一个字符串来描述朋友的回答,2个数中间用空格分隔,分别表示区间的起点和终点,后面的字符为"even"或"odd",表示朋友的答案。
Output
输出1个数,表示朋友的答案中第一个错误答案的位置,如果所有答案均不矛盾,则输出-1。
Input示例
10 5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd
Output示例
4

如果S[a]到S[b]是偶数,说明S[a-1]和S[b]是相同的值。划分到一个集里面去。

如果S[a]到S[b]是奇数,说明S[a-1]和S[b]是不同的值。将S[a-1+n]和S[b]划分到一个集里面去。

代码:

#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;

#define INF 0x3fffffff
const int mod = 1e9 + 7;
const int maxn = 200005;

int n, q;
int pre[maxn];

void init()
{
	int i;
	for (i = 0; i < maxn; i++)
	{
		pre[i] = i;
	}
}

int fa(int x)
{
	while (pre[x] != x)
	{
		x = pre[x];
	}
	return x;
}

void uni(int x, int y)
{
	x = fa(x);
	y = fa(y);

	if (x > y)
	{
		x ^= y ^= x ^= y;
	}
	pre[x] = y;
}

void solve()
{
	int i, flag;
	int s, e;
	char ch[10];

	scanf("%d%d", &n, &q);

	flag = 0;
	for (i = 1; i <= q; i++)
	{
		scanf("%d%d%s", &s, &e, ch);
		if (flag)continue;
		if (strcmp(ch, "even") == 0)
		{
			if (fa(s - 1 + n) == fa(e) && fa(s - 1) == fa(e + n))
			{
				flag = i;
			}
			else
			{
				uni(s - 1, e);
				uni(s - 1 + n, e + n);
			}
		}
		else
		{
			if (fa(s - 1) == fa(e) && fa(s - 1 + n) == fa(e + n))
			{
				flag = i;
			}
			else
			{
				uni(s - 1, e + n);
				uni(s - 1 + n, e);
			}
		}
	}
	if (flag)
	{
		printf("%d\n", flag);
	}
	else
	{
		puts("-1");
	}
}

int main()
{
	//freopen("i.txt", "r", stdin);
	//freopen("o.txt", "w", stdout);

	init();
	solve();

	//system("pause");
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值